NOISSUE Refactors and moving of things
This commit is contained in:
parent
593111b144
commit
791221e923
@ -394,6 +394,8 @@ SET(MULTIMC_SOURCES
|
|||||||
|
|
||||||
# LOGIC - Base classes and infrastructure
|
# LOGIC - Base classes and infrastructure
|
||||||
logic/BaseVersion.h
|
logic/BaseVersion.h
|
||||||
|
logic/BaseProcess.h
|
||||||
|
logic/BaseProcess.cpp
|
||||||
logic/InstanceFactory.h
|
logic/InstanceFactory.h
|
||||||
logic/InstanceFactory.cpp
|
logic/InstanceFactory.cpp
|
||||||
logic/BaseInstance.h
|
logic/BaseInstance.h
|
||||||
@ -404,12 +406,8 @@ SET(MULTIMC_SOURCES
|
|||||||
logic/ModList.cpp
|
logic/ModList.cpp
|
||||||
|
|
||||||
# sets and maps for deciding based on versions
|
# sets and maps for deciding based on versions
|
||||||
logic/VersionFilterData.h
|
logic/minecraft/VersionFilterData.h
|
||||||
logic/VersionFilterData.cpp
|
logic/minecraft/VersionFilterData.cpp
|
||||||
|
|
||||||
# Instance launch
|
|
||||||
logic/MinecraftProcess.h
|
|
||||||
logic/MinecraftProcess.cpp
|
|
||||||
|
|
||||||
# Annoying nag screen logic
|
# Annoying nag screen logic
|
||||||
logic/NagUtils.h
|
logic/NagUtils.h
|
||||||
@ -503,24 +501,34 @@ SET(MULTIMC_SOURCES
|
|||||||
logic/JarUtils.h
|
logic/JarUtils.h
|
||||||
logic/JarUtils.cpp
|
logic/JarUtils.cpp
|
||||||
|
|
||||||
# OneSix version json infrastructure
|
# Minecraft support
|
||||||
logic/minecraft/GradleSpecifier.h
|
logic/minecraft/GradleSpecifier.h
|
||||||
logic/minecraft/InstanceVersion.cpp
|
logic/minecraft/MinecraftProfile.cpp
|
||||||
logic/minecraft/InstanceVersion.h
|
logic/minecraft/MinecraftProfile.h
|
||||||
logic/minecraft/JarMod.cpp
|
logic/minecraft/JarMod.cpp
|
||||||
logic/minecraft/JarMod.h
|
logic/minecraft/JarMod.h
|
||||||
|
logic/minecraft/MinecraftInstance.cpp
|
||||||
|
logic/minecraft/MinecraftInstance.h
|
||||||
|
logic/minecraft/MinecraftProcess.cpp
|
||||||
|
logic/minecraft/MinecraftProcess.h
|
||||||
logic/minecraft/MinecraftVersion.cpp
|
logic/minecraft/MinecraftVersion.cpp
|
||||||
logic/minecraft/MinecraftVersion.h
|
logic/minecraft/MinecraftVersion.h
|
||||||
logic/minecraft/MinecraftVersionList.cpp
|
logic/minecraft/MinecraftVersionList.cpp
|
||||||
logic/minecraft/MinecraftVersionList.h
|
logic/minecraft/MinecraftVersionList.h
|
||||||
|
logic/minecraft/NullProfileStrategy.h
|
||||||
logic/minecraft/OneSixLibrary.cpp
|
logic/minecraft/OneSixLibrary.cpp
|
||||||
logic/minecraft/OneSixLibrary.h
|
logic/minecraft/OneSixLibrary.h
|
||||||
|
logic/minecraft/OneSixProfileStrategy.cpp
|
||||||
|
logic/minecraft/OneSixProfileStrategy.h
|
||||||
logic/minecraft/OneSixRule.cpp
|
logic/minecraft/OneSixRule.cpp
|
||||||
logic/minecraft/OneSixRule.h
|
logic/minecraft/OneSixRule.h
|
||||||
logic/minecraft/OpSys.cpp
|
logic/minecraft/OpSys.cpp
|
||||||
logic/minecraft/OpSys.h
|
logic/minecraft/OpSys.h
|
||||||
logic/minecraft/ParseUtils.cpp
|
logic/minecraft/ParseUtils.cpp
|
||||||
logic/minecraft/ParseUtils.h
|
logic/minecraft/ParseUtils.h
|
||||||
|
logic/minecraft/ProfileUtils.cpp
|
||||||
|
logic/minecraft/ProfileUtils.h
|
||||||
|
logic/minecraft/ProfileStrategy.h
|
||||||
logic/minecraft/RawLibrary.cpp
|
logic/minecraft/RawLibrary.cpp
|
||||||
logic/minecraft/RawLibrary.h
|
logic/minecraft/RawLibrary.h
|
||||||
logic/minecraft/VersionBuilder.cpp
|
logic/minecraft/VersionBuilder.cpp
|
||||||
@ -528,7 +536,7 @@ SET(MULTIMC_SOURCES
|
|||||||
logic/minecraft/VersionBuildError.h
|
logic/minecraft/VersionBuildError.h
|
||||||
logic/minecraft/VersionFile.cpp
|
logic/minecraft/VersionFile.cpp
|
||||||
logic/minecraft/VersionFile.h
|
logic/minecraft/VersionFile.h
|
||||||
logic/minecraft/VersionPatch.h
|
logic/minecraft/ProfilePatch.h
|
||||||
logic/minecraft/VersionSource.h
|
logic/minecraft/VersionSource.h
|
||||||
|
|
||||||
# A Recursive file system watcher
|
# A Recursive file system watcher
|
||||||
@ -547,10 +555,10 @@ SET(MULTIMC_SOURCES
|
|||||||
logic/LwjglVersionList.cpp
|
logic/LwjglVersionList.cpp
|
||||||
|
|
||||||
# FTB
|
# FTB
|
||||||
logic/OneSixFTBInstance.h
|
logic/ftb/OneSixFTBInstance.h
|
||||||
logic/OneSixFTBInstance.cpp
|
logic/ftb/OneSixFTBInstance.cpp
|
||||||
logic/LegacyFTBInstance.h
|
logic/ftb/LegacyFTBInstance.h
|
||||||
logic/LegacyFTBInstance.cpp
|
logic/ftb/LegacyFTBInstance.cpp
|
||||||
|
|
||||||
# the screenshots feature
|
# the screenshots feature
|
||||||
logic/screenshots/Screenshot.h
|
logic/screenshots/Screenshot.h
|
||||||
@ -597,8 +605,6 @@ SET(MULTIMC_SOURCES
|
|||||||
logic/java/JavaCheckerJob.cpp
|
logic/java/JavaCheckerJob.cpp
|
||||||
|
|
||||||
# Assets
|
# Assets
|
||||||
logic/assets/AssetsMigrateTask.h
|
|
||||||
logic/assets/AssetsMigrateTask.cpp
|
|
||||||
logic/assets/AssetsUtils.h
|
logic/assets/AssetsUtils.h
|
||||||
logic/assets/AssetsUtils.cpp
|
logic/assets/AssetsUtils.cpp
|
||||||
|
|
||||||
|
21
MultiMC.cpp
21
MultiMC.cpp
@ -21,8 +21,6 @@
|
|||||||
|
|
||||||
#include "logic/forge/ForgeVersionList.h"
|
#include "logic/forge/ForgeVersionList.h"
|
||||||
|
|
||||||
#include "logic/news/NewsChecker.h"
|
|
||||||
|
|
||||||
#include "logic/status/StatusChecker.h"
|
#include "logic/status/StatusChecker.h"
|
||||||
|
|
||||||
#include "logic/net/HttpMetaCache.h"
|
#include "logic/net/HttpMetaCache.h"
|
||||||
@ -201,9 +199,6 @@ MultiMC::MultiMC(int &argc, char **argv, bool test_mode) : QApplication(argc, ar
|
|||||||
// initialize the notification checker
|
// initialize the notification checker
|
||||||
m_notificationChecker.reset(new NotificationChecker());
|
m_notificationChecker.reset(new NotificationChecker());
|
||||||
|
|
||||||
// initialize the news checker
|
|
||||||
m_newsChecker.reset(new NewsChecker(BuildConfig.NEWS_RSS_URL));
|
|
||||||
|
|
||||||
// initialize the status checker
|
// initialize the status checker
|
||||||
m_statusChecker.reset(new StatusChecker());
|
m_statusChecker.reset(new StatusChecker());
|
||||||
|
|
||||||
@ -213,7 +208,7 @@ MultiMC::MultiMC(int &argc, char **argv, bool test_mode) : QApplication(argc, ar
|
|||||||
auto InstDirSetting = m_settings->getSetting("InstanceDir");
|
auto InstDirSetting = m_settings->getSetting("InstanceDir");
|
||||||
// instance path: check for problems with '!' in instance path and warn the user in the log
|
// instance path: check for problems with '!' in instance path and warn the user in the log
|
||||||
// and rememer that we have to show him a dialog when the gui starts (if it does so)
|
// and rememer that we have to show him a dialog when the gui starts (if it does so)
|
||||||
QString instDir = MMC->settings()->get("InstanceDir").toString();
|
QString instDir = m_settings->get("InstanceDir").toString();
|
||||||
QLOG_INFO() << "Instance path : " << instDir;
|
QLOG_INFO() << "Instance path : " << instDir;
|
||||||
if (checkProblemticPathJava(QDir(instDir)))
|
if (checkProblemticPathJava(QDir(instDir)))
|
||||||
{
|
{
|
||||||
@ -243,6 +238,7 @@ MultiMC::MultiMC(int &argc, char **argv, bool test_mode) : QApplication(argc, ar
|
|||||||
// init proxy settings
|
// init proxy settings
|
||||||
updateProxySettings();
|
updateProxySettings();
|
||||||
|
|
||||||
|
//FIXME: what to do with these?
|
||||||
m_profilers.insert("jprofiler",
|
m_profilers.insert("jprofiler",
|
||||||
std::shared_ptr<BaseProfilerFactory>(new JProfilerFactory()));
|
std::shared_ptr<BaseProfilerFactory>(new JProfilerFactory()));
|
||||||
m_profilers.insert("jvisualvm",
|
m_profilers.insert("jvisualvm",
|
||||||
@ -251,6 +247,8 @@ MultiMC::MultiMC(int &argc, char **argv, bool test_mode) : QApplication(argc, ar
|
|||||||
{
|
{
|
||||||
profiler->registerSettings(m_settings);
|
profiler->registerSettings(m_settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//FIXME: what to do with these?
|
||||||
m_tools.insert("mcedit", std::shared_ptr<BaseDetachedToolFactory>(new MCEditFactory()));
|
m_tools.insert("mcedit", std::shared_ptr<BaseDetachedToolFactory>(new MCEditFactory()));
|
||||||
for (auto tool : m_tools.values())
|
for (auto tool : m_tools.values())
|
||||||
{
|
{
|
||||||
@ -296,8 +294,7 @@ void MultiMC::initTranslations()
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_mmc_translator.reset(new QTranslator());
|
m_mmc_translator.reset(new QTranslator());
|
||||||
if (m_mmc_translator->load("mmc_" + locale.bcp47Name(),
|
if (m_mmc_translator->load("mmc_" + locale.bcp47Name(), staticData() + "/translations"))
|
||||||
MMC->staticData() + "/translations"))
|
|
||||||
{
|
{
|
||||||
QLOG_DEBUG() << "Loading MMC Language File for"
|
QLOG_DEBUG() << "Loading MMC Language File for"
|
||||||
<< locale.bcp47Name().toLocal8Bit().constData() << "...";
|
<< locale.bcp47Name().toLocal8Bit().constData() << "...";
|
||||||
@ -701,13 +698,13 @@ void MultiMC::installUpdates(const QString updateFilesDir, UpdateFlags flags)
|
|||||||
}
|
}
|
||||||
QLOG_INFO() << "Installing updates.";
|
QLOG_INFO() << "Installing updates.";
|
||||||
#ifdef WINDOWS
|
#ifdef WINDOWS
|
||||||
QString finishCmd = MMC->applicationFilePath();
|
QString finishCmd = applicationFilePath();
|
||||||
QString updaterBinary = PathCombine(bin(), "updater.exe");
|
QString updaterBinary = PathCombine(bin(), "updater.exe");
|
||||||
#elif LINUX
|
#elif LINUX
|
||||||
QString finishCmd = PathCombine(root(), "MultiMC");
|
QString finishCmd = PathCombine(root(), "MultiMC");
|
||||||
QString updaterBinary = PathCombine(bin(), "updater");
|
QString updaterBinary = PathCombine(bin(), "updater");
|
||||||
#elif OSX
|
#elif OSX
|
||||||
QString finishCmd = MMC->applicationFilePath();
|
QString finishCmd = applicationFilePath();
|
||||||
QString updaterBinary = PathCombine(bin(), "updater");
|
QString updaterBinary = PathCombine(bin(), "updater");
|
||||||
#else
|
#else
|
||||||
#error Unsupported operating system.
|
#error Unsupported operating system.
|
||||||
@ -719,7 +716,7 @@ void MultiMC::installUpdates(const QString updateFilesDir, UpdateFlags flags)
|
|||||||
args << "--install-dir" << root();
|
args << "--install-dir" << root();
|
||||||
args << "--package-dir" << updateFilesDir;
|
args << "--package-dir" << updateFilesDir;
|
||||||
args << "--script" << PathCombine(updateFilesDir, "file_list.xml");
|
args << "--script" << PathCombine(updateFilesDir, "file_list.xml");
|
||||||
args << "--wait" << QString::number(MMC->applicationPid());
|
args << "--wait" << QString::number(applicationPid());
|
||||||
if (flags & DryRun)
|
if (flags & DryRun)
|
||||||
args << "--dry-run";
|
args << "--dry-run";
|
||||||
if (flags & RestartOnFinish)
|
if (flags & RestartOnFinish)
|
||||||
@ -737,7 +734,7 @@ void MultiMC::installUpdates(const QString updateFilesDir, UpdateFlags flags)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Now that we've started the updater, quit MultiMC.
|
// Now that we've started the updater, quit MultiMC.
|
||||||
MMC->quit();
|
quit();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MultiMC::setIconTheme(const QString& name)
|
void MultiMC::setIconTheme(const QString& name)
|
||||||
|
@ -20,7 +20,6 @@ class LiteLoaderVersionList;
|
|||||||
class JavaVersionList;
|
class JavaVersionList;
|
||||||
class UpdateChecker;
|
class UpdateChecker;
|
||||||
class NotificationChecker;
|
class NotificationChecker;
|
||||||
class NewsChecker;
|
|
||||||
class StatusChecker;
|
class StatusChecker;
|
||||||
class BaseProfilerFactory;
|
class BaseProfilerFactory;
|
||||||
class BaseDetachedToolFactory;
|
class BaseDetachedToolFactory;
|
||||||
@ -102,11 +101,6 @@ public:
|
|||||||
return m_notificationChecker;
|
return m_notificationChecker;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<NewsChecker> newsChecker()
|
|
||||||
{
|
|
||||||
return m_newsChecker;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<StatusChecker> statusChecker()
|
std::shared_ptr<StatusChecker> statusChecker()
|
||||||
{
|
{
|
||||||
return m_statusChecker;
|
return m_statusChecker;
|
||||||
@ -197,7 +191,6 @@ private:
|
|||||||
std::shared_ptr<InstanceList> m_instances;
|
std::shared_ptr<InstanceList> m_instances;
|
||||||
std::shared_ptr<UpdateChecker> m_updateChecker;
|
std::shared_ptr<UpdateChecker> m_updateChecker;
|
||||||
std::shared_ptr<NotificationChecker> m_notificationChecker;
|
std::shared_ptr<NotificationChecker> m_notificationChecker;
|
||||||
std::shared_ptr<NewsChecker> m_newsChecker;
|
|
||||||
std::shared_ptr<StatusChecker> m_statusChecker;
|
std::shared_ptr<StatusChecker> m_statusChecker;
|
||||||
std::shared_ptr<MojangAccountList> m_accounts;
|
std::shared_ptr<MojangAccountList> m_accounts;
|
||||||
std::shared_ptr<IconList> m_icons;
|
std::shared_ptr<IconList> m_icons;
|
||||||
|
@ -30,24 +30,76 @@ private:
|
|||||||
QString m_string;
|
QString m_string;
|
||||||
struct Section
|
struct Section
|
||||||
{
|
{
|
||||||
explicit Section(const QString &str, const int num) : numValid(true), number(num), string(str) {}
|
explicit Section(const QString &fullString)
|
||||||
explicit Section(const QString &str) : numValid(false), string(str) {}
|
{
|
||||||
|
m_fullString = fullString;
|
||||||
|
int cutoff = m_fullString.size();
|
||||||
|
for(int i = 0; i < m_fullString.size(); i++)
|
||||||
|
{
|
||||||
|
if(!m_fullString[i].isDigit())
|
||||||
|
{
|
||||||
|
cutoff = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
auto numPart = m_fullString.leftRef(cutoff);
|
||||||
|
if(numPart.size())
|
||||||
|
{
|
||||||
|
numValid = true;
|
||||||
|
m_numPart = numPart.toInt();
|
||||||
|
}
|
||||||
|
auto stringPart = m_fullString.midRef(cutoff);
|
||||||
|
if(stringPart.size())
|
||||||
|
{
|
||||||
|
m_stringPart = stringPart.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
explicit Section() {}
|
explicit Section() {}
|
||||||
bool numValid;
|
bool numValid = false;
|
||||||
int number;
|
int m_numPart = 0;
|
||||||
QString string;
|
QString m_stringPart;
|
||||||
|
QString m_fullString;
|
||||||
|
|
||||||
inline bool operator!=(const Section &other) const
|
inline bool operator!=(const Section &other) const
|
||||||
{
|
{
|
||||||
return (numValid && other.numValid) ? (number != other.number) : (string != other.string);
|
if(numValid && other.numValid)
|
||||||
|
{
|
||||||
|
return m_numPart != other.m_numPart || m_stringPart != other.m_stringPart;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return m_fullString != other.m_fullString;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
inline bool operator<(const Section &other) const
|
inline bool operator<(const Section &other) const
|
||||||
{
|
{
|
||||||
return (numValid && other.numValid) ? (number < other.number) : (string < other.string);
|
if(numValid && other.numValid)
|
||||||
|
{
|
||||||
|
if(m_numPart < other.m_numPart)
|
||||||
|
return true;
|
||||||
|
if(m_numPart == other.m_numPart && m_stringPart < other.m_stringPart)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return m_fullString < other.m_fullString;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
inline bool operator>(const Section &other) const
|
inline bool operator>(const Section &other) const
|
||||||
{
|
{
|
||||||
return (numValid && other.numValid) ? (number > other.number) : (string > other.string);
|
if(numValid && other.numValid)
|
||||||
|
{
|
||||||
|
if(m_numPart > other.m_numPart)
|
||||||
|
return true;
|
||||||
|
if(m_numPart == other.m_numPart && m_stringPart > other.m_stringPart)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return m_fullString > other.m_fullString;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
QList<Section> m_sections;
|
QList<Section> m_sections;
|
||||||
|
@ -15,9 +15,9 @@ bool Util::Version::operator<(const Version &other) const
|
|||||||
const int size = qMax(m_sections.size(), other.m_sections.size());
|
const int size = qMax(m_sections.size(), other.m_sections.size());
|
||||||
for (int i = 0; i < size; ++i)
|
for (int i = 0; i < size; ++i)
|
||||||
{
|
{
|
||||||
const Section sec1 = (i >= m_sections.size()) ? Section("0", 0) : m_sections.at(i);
|
const Section sec1 = (i >= m_sections.size()) ? Section("0") : m_sections.at(i);
|
||||||
const Section sec2 =
|
const Section sec2 =
|
||||||
(i >= other.m_sections.size()) ? Section("0", 0) : other.m_sections.at(i);
|
(i >= other.m_sections.size()) ? Section("0") : other.m_sections.at(i);
|
||||||
if (sec1 != sec2)
|
if (sec1 != sec2)
|
||||||
{
|
{
|
||||||
return sec1 < sec2;
|
return sec1 < sec2;
|
||||||
@ -35,9 +35,9 @@ bool Util::Version::operator>(const Version &other) const
|
|||||||
const int size = qMax(m_sections.size(), other.m_sections.size());
|
const int size = qMax(m_sections.size(), other.m_sections.size());
|
||||||
for (int i = 0; i < size; ++i)
|
for (int i = 0; i < size; ++i)
|
||||||
{
|
{
|
||||||
const Section sec1 = (i >= m_sections.size()) ? Section("0", 0) : m_sections.at(i);
|
const Section sec1 = (i >= m_sections.size()) ? Section("0") : m_sections.at(i);
|
||||||
const Section sec2 =
|
const Section sec2 =
|
||||||
(i >= other.m_sections.size()) ? Section("0", 0) : other.m_sections.at(i);
|
(i >= other.m_sections.size()) ? Section("0") : other.m_sections.at(i);
|
||||||
if (sec1 != sec2)
|
if (sec1 != sec2)
|
||||||
{
|
{
|
||||||
return sec1 > sec2;
|
return sec1 > sec2;
|
||||||
@ -55,9 +55,9 @@ bool Util::Version::operator==(const Version &other) const
|
|||||||
const int size = qMax(m_sections.size(), other.m_sections.size());
|
const int size = qMax(m_sections.size(), other.m_sections.size());
|
||||||
for (int i = 0; i < size; ++i)
|
for (int i = 0; i < size; ++i)
|
||||||
{
|
{
|
||||||
const Section sec1 = (i >= m_sections.size()) ? Section("0", 0) : m_sections.at(i);
|
const Section sec1 = (i >= m_sections.size()) ? Section("0") : m_sections.at(i);
|
||||||
const Section sec2 =
|
const Section sec2 =
|
||||||
(i >= other.m_sections.size()) ? Section("0", 0) : other.m_sections.at(i);
|
(i >= other.m_sections.size()) ? Section("0") : other.m_sections.at(i);
|
||||||
if (sec1 != sec2)
|
if (sec1 != sec2)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@ -78,19 +78,10 @@ void Util::Version::parse()
|
|||||||
QStringList parts = m_string.split('.');
|
QStringList parts = m_string.split('.');
|
||||||
|
|
||||||
for (const auto part : parts)
|
for (const auto part : parts)
|
||||||
{
|
|
||||||
bool ok = false;
|
|
||||||
int num = part.toInt(&ok);
|
|
||||||
if (ok)
|
|
||||||
{
|
|
||||||
m_sections.append(Section(part, num));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
m_sections.append(Section(part));
|
m_sections.append(Section(part));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
bool Util::versionIsInInterval(const QString &version, const QString &interval)
|
bool Util::versionIsInInterval(const QString &version, const QString &interval)
|
||||||
{
|
{
|
||||||
|
@ -52,8 +52,8 @@ private:
|
|||||||
BasePage * m_log_page;
|
BasePage * m_log_page;
|
||||||
};
|
};
|
||||||
|
|
||||||
ConsoleWindow::ConsoleWindow(MinecraftProcess *mcproc, QWidget *parent)
|
ConsoleWindow::ConsoleWindow(BaseProcess *process, QWidget *parent)
|
||||||
: QMainWindow(parent), m_proc(mcproc)
|
: QMainWindow(parent), m_proc(process)
|
||||||
{
|
{
|
||||||
MultiMCPlatform::fixWM_CLASS(this);
|
MultiMCPlatform::fixWM_CLASS(this);
|
||||||
setAttribute(Qt::WA_DeleteOnClose);
|
setAttribute(Qt::WA_DeleteOnClose);
|
||||||
@ -127,16 +127,16 @@ ConsoleWindow::ConsoleWindow(MinecraftProcess *mcproc, QWidget *parent)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set up signal connections
|
// Set up signal connections
|
||||||
connect(mcproc, SIGNAL(ended(InstancePtr, int, QProcess::ExitStatus)), this,
|
connect(m_proc, SIGNAL(ended(InstancePtr, int, QProcess::ExitStatus)), this,
|
||||||
SLOT(onEnded(InstancePtr, int, QProcess::ExitStatus)));
|
SLOT(onEnded(InstancePtr, int, QProcess::ExitStatus)));
|
||||||
connect(mcproc, SIGNAL(prelaunch_failed(InstancePtr, int, QProcess::ExitStatus)), this,
|
connect(m_proc, SIGNAL(prelaunch_failed(InstancePtr, int, QProcess::ExitStatus)), this,
|
||||||
SLOT(onEnded(InstancePtr, int, QProcess::ExitStatus)));
|
SLOT(onEnded(InstancePtr, int, QProcess::ExitStatus)));
|
||||||
connect(mcproc, SIGNAL(launch_failed(InstancePtr)), this,
|
connect(m_proc, SIGNAL(launch_failed(InstancePtr)), this,
|
||||||
SLOT(onLaunchFailed(InstancePtr)));
|
SLOT(onLaunchFailed(InstancePtr)));
|
||||||
|
|
||||||
setMayClose(false);
|
setMayClose(false);
|
||||||
|
|
||||||
if (mcproc->instance()->settings().get("ShowConsole").toBool())
|
if (m_proc->instance()->settings().get("ShowConsole").toBool())
|
||||||
{
|
{
|
||||||
show();
|
show();
|
||||||
}
|
}
|
||||||
@ -213,7 +213,7 @@ void ConsoleWindow::on_btnKillMinecraft_clicked()
|
|||||||
"is frozen for some reason"),
|
"is frozen for some reason"),
|
||||||
QMessageBox::Question, QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes)->exec();
|
QMessageBox::Question, QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes)->exec();
|
||||||
if (response == QMessageBox::Yes)
|
if (response == QMessageBox::Yes)
|
||||||
m_proc->killMinecraft();
|
m_proc->killProcess();
|
||||||
else
|
else
|
||||||
m_killButton->setEnabled(true);
|
m_killButton->setEnabled(true);
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
#include <QMainWindow>
|
#include <QMainWindow>
|
||||||
#include <QSystemTrayIcon>
|
#include <QSystemTrayIcon>
|
||||||
#include "logic/MinecraftProcess.h"
|
#include "logic/BaseProcess.h"
|
||||||
|
|
||||||
class QPushButton;
|
class QPushButton;
|
||||||
class PageContainer;
|
class PageContainer;
|
||||||
@ -26,7 +26,7 @@ class ConsoleWindow : public QMainWindow
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit ConsoleWindow(MinecraftProcess *proc, QWidget *parent = 0);
|
explicit ConsoleWindow(BaseProcess *proc, QWidget *parent = 0);
|
||||||
virtual ~ConsoleWindow();
|
virtual ~ConsoleWindow();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -56,7 +56,7 @@ protected:
|
|||||||
void closeEvent(QCloseEvent *);
|
void closeEvent(QCloseEvent *);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MinecraftProcess *m_proc = nullptr;
|
BaseProcess *m_proc = nullptr;
|
||||||
bool m_mayclose = true;
|
bool m_mayclose = true;
|
||||||
QSystemTrayIcon *m_trayIcon = nullptr;
|
QSystemTrayIcon *m_trayIcon = nullptr;
|
||||||
PageContainer *m_container = nullptr;
|
PageContainer *m_container = nullptr;
|
||||||
|
@ -381,7 +381,7 @@ namespace Ui {
|
|||||||
#include "logic/BaseInstance.h"
|
#include "logic/BaseInstance.h"
|
||||||
#include "logic/OneSixInstance.h"
|
#include "logic/OneSixInstance.h"
|
||||||
#include "logic/InstanceFactory.h"
|
#include "logic/InstanceFactory.h"
|
||||||
#include "logic/MinecraftProcess.h"
|
#include "logic/BaseProcess.h"
|
||||||
#include "logic/OneSixUpdate.h"
|
#include "logic/OneSixUpdate.h"
|
||||||
#include "logic/java/JavaUtils.h"
|
#include "logic/java/JavaUtils.h"
|
||||||
#include "logic/NagUtils.h"
|
#include "logic/NagUtils.h"
|
||||||
@ -403,6 +403,9 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi
|
|||||||
MultiMCPlatform::fixWM_CLASS(this);
|
MultiMCPlatform::fixWM_CLASS(this);
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
|
||||||
|
// initialize the news checker
|
||||||
|
m_newsChecker.reset(new NewsChecker(BuildConfig.NEWS_RSS_URL));
|
||||||
|
|
||||||
QString winTitle =
|
QString winTitle =
|
||||||
QString("MultiMC 5 - Version %1").arg(BuildConfig.printableVersionString());
|
QString("MultiMC 5 - Version %1").arg(BuildConfig.printableVersionString());
|
||||||
if (!BuildConfig.BUILD_PLATFORM.isEmpty())
|
if (!BuildConfig.BUILD_PLATFORM.isEmpty())
|
||||||
@ -443,7 +446,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi
|
|||||||
ui->newsToolBar->insertWidget(ui->actionMoreNews, newsLabel);
|
ui->newsToolBar->insertWidget(ui->actionMoreNews, newsLabel);
|
||||||
QObject::connect(newsLabel, &QAbstractButton::clicked, this,
|
QObject::connect(newsLabel, &QAbstractButton::clicked, this,
|
||||||
&MainWindow::newsButtonClicked);
|
&MainWindow::newsButtonClicked);
|
||||||
QObject::connect(MMC->newsChecker().get(), &NewsChecker::newsLoaded, this,
|
QObject::connect(m_newsChecker.get(), &NewsChecker::newsLoaded, this,
|
||||||
&MainWindow::updateNewsLabel);
|
&MainWindow::updateNewsLabel);
|
||||||
updateNewsLabel();
|
updateNewsLabel();
|
||||||
}
|
}
|
||||||
@ -606,7 +609,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi
|
|||||||
MMC->lwjgllist()->loadList();
|
MMC->lwjgllist()->loadList();
|
||||||
}
|
}
|
||||||
|
|
||||||
MMC->newsChecker()->reloadNews();
|
m_newsChecker->reloadNews();
|
||||||
updateNewsLabel();
|
updateNewsLabel();
|
||||||
|
|
||||||
// set up the updater object.
|
// set up the updater object.
|
||||||
@ -888,15 +891,14 @@ bool MainWindow::eventFilter(QObject *obj, QEvent *ev)
|
|||||||
|
|
||||||
void MainWindow::updateNewsLabel()
|
void MainWindow::updateNewsLabel()
|
||||||
{
|
{
|
||||||
auto newsChecker = MMC->newsChecker();
|
if (m_newsChecker->isLoadingNews())
|
||||||
if (newsChecker->isLoadingNews())
|
|
||||||
{
|
{
|
||||||
newsLabel->setText(tr("Loading news..."));
|
newsLabel->setText(tr("Loading news..."));
|
||||||
newsLabel->setEnabled(false);
|
newsLabel->setEnabled(false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
QList<NewsEntryPtr> entries = newsChecker->getNewsEntries();
|
QList<NewsEntryPtr> entries = m_newsChecker->getNewsEntries();
|
||||||
if (entries.length() > 0)
|
if (entries.length() > 0)
|
||||||
{
|
{
|
||||||
newsLabel->setText(entries[0]->title);
|
newsLabel->setText(entries[0]->title);
|
||||||
@ -1041,7 +1043,9 @@ static QFileInfo findRecursive(const QString &dir, const QString &name)
|
|||||||
}
|
}
|
||||||
return QFileInfo();
|
return QFileInfo();
|
||||||
}
|
}
|
||||||
void MainWindow::on_actionAddInstance_triggered()
|
|
||||||
|
// FIXME: eliminate, should not be needed
|
||||||
|
void MainWindow::waitForMinecraftVersions()
|
||||||
{
|
{
|
||||||
if (!MMC->minecraftlist()->isLoaded() && m_versionLoadTask &&
|
if (!MMC->minecraftlist()->isLoaded() && m_versionLoadTask &&
|
||||||
m_versionLoadTask->isRunning())
|
m_versionLoadTask->isRunning())
|
||||||
@ -1051,33 +1055,26 @@ void MainWindow::on_actionAddInstance_triggered()
|
|||||||
waitLoop.connect(m_versionLoadTask, SIGNAL(succeeded()), SLOT(quit()));
|
waitLoop.connect(m_versionLoadTask, SIGNAL(succeeded()), SLOT(quit()));
|
||||||
waitLoop.exec();
|
waitLoop.exec();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
NewInstanceDialog newInstDlg(this);
|
void MainWindow::instanceFromZipPack(QString instName, QString instGroup, QString instIcon, QUrl url)
|
||||||
if (!newInstDlg.exec())
|
{
|
||||||
return;
|
|
||||||
|
|
||||||
MMC->settings()->set("LastUsedGroupForNewInstance", newInstDlg.instGroup());
|
|
||||||
|
|
||||||
InstancePtr newInstance;
|
InstancePtr newInstance;
|
||||||
|
|
||||||
QString instancesDir = MMC->settings()->get("InstanceDir").toString();
|
QString instancesDir = MMC->settings()->get("InstanceDir").toString();
|
||||||
QString instDirName = DirNameFromString(newInstDlg.instName(), instancesDir);
|
QString instDirName = DirNameFromString(instName, instancesDir);
|
||||||
QString instDir = PathCombine(instancesDir, instDirName);
|
QString instDir = PathCombine(instancesDir, instDirName);
|
||||||
auto &loader = InstanceFactory::get();
|
auto &loader = InstanceFactory::get();
|
||||||
|
|
||||||
const QUrl modpackUrl = newInstDlg.modpackUrl();
|
|
||||||
if (modpackUrl.isValid())
|
|
||||||
{
|
|
||||||
QString archivePath;
|
QString archivePath;
|
||||||
if (modpackUrl.isLocalFile())
|
if (url.isLocalFile())
|
||||||
{
|
{
|
||||||
archivePath = modpackUrl.toLocalFile();
|
archivePath = url.toLocalFile();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const QString path = modpackUrl.host() + '/' + modpackUrl.path();
|
const QString path = url.host() + '/' + url.path();
|
||||||
auto entry = MMC->metacache()->resolveEntry("general", path);
|
auto entry = MMC->metacache()->resolveEntry("general", path);
|
||||||
CacheDownloadPtr dl = CacheDownload::make(modpackUrl, entry);
|
CacheDownloadPtr dl = CacheDownload::make(url, entry);
|
||||||
NetJob job(tr("Modpack download"));
|
NetJob job(tr("Modpack download"));
|
||||||
job.addNetAction(dl);
|
job.addNetAction(dl);
|
||||||
|
|
||||||
@ -1087,11 +1084,9 @@ void MainWindow::on_actionAddInstance_triggered()
|
|||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
archivePath = entry->getFullPath();
|
archivePath = entry->getFullPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
QTemporaryDir extractTmpDir;
|
QTemporaryDir extractTmpDir;
|
||||||
QDir extractDir(extractTmpDir.path());
|
QDir extractDir(extractTmpDir.path());
|
||||||
QLOG_INFO() << "Attempting to create instance from" << archivePath;
|
QLOG_INFO() << "Attempting to create instance from" << archivePath;
|
||||||
@ -1126,10 +1121,25 @@ void MainWindow::on_actionAddInstance_triggered()
|
|||||||
CustomMessageBox::selectable(this, tr("Error"), errorMsg, QMessageBox::Warning)->show();
|
CustomMessageBox::selectable(this, tr("Error"), errorMsg, QMessageBox::Warning)->show();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
newInstance->setName(instName);
|
||||||
|
newInstance->setIconKey(instIcon);
|
||||||
|
newInstance->setGroupInitial(instGroup);
|
||||||
|
MMC->instances()->add(InstancePtr(newInstance));
|
||||||
|
MMC->instances()->saveGroupList();
|
||||||
|
|
||||||
|
finalizeInstance(newInstance);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
void MainWindow::instanceFromVersion(QString instName, QString instGroup, QString instIcon, BaseVersionPtr version)
|
||||||
{
|
{
|
||||||
auto error = loader.createInstance(newInstance, newInstDlg.selectedVersion(), instDir);
|
InstancePtr newInstance;
|
||||||
|
|
||||||
|
QString instancesDir = MMC->settings()->get("InstanceDir").toString();
|
||||||
|
QString instDirName = DirNameFromString(instName, instancesDir);
|
||||||
|
QString instDir = PathCombine(instancesDir, instDirName);
|
||||||
|
auto &loader = InstanceFactory::get();
|
||||||
|
auto error = loader.createInstance(newInstance, version, instDir);
|
||||||
QString errorMsg = tr("Failed to create instance %1: ").arg(instDirName);
|
QString errorMsg = tr("Failed to create instance %1: ").arg(instDirName);
|
||||||
switch (error)
|
switch (error)
|
||||||
{
|
{
|
||||||
@ -1155,17 +1165,20 @@ void MainWindow::on_actionAddInstance_triggered()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
newInstance->setName(instName);
|
||||||
|
newInstance->setIconKey(instIcon);
|
||||||
|
newInstance->setGroupInitial(instGroup);
|
||||||
|
MMC->instances()->add(InstancePtr(newInstance));
|
||||||
|
MMC->instances()->saveGroupList();
|
||||||
|
finalizeInstance(newInstance);
|
||||||
}
|
}
|
||||||
|
|
||||||
newInstance->setName(newInstDlg.instName());
|
void MainWindow::finalizeInstance(InstancePtr inst)
|
||||||
newInstance->setIconKey(newInstDlg.iconKey());
|
{
|
||||||
newInstance->setGroupInitial(newInstDlg.instGroup());
|
|
||||||
MMC->instances()->add(InstancePtr(newInstance));
|
|
||||||
|
|
||||||
if (MMC->accounts()->anyAccountIsValid())
|
if (MMC->accounts()->anyAccountIsValid())
|
||||||
{
|
{
|
||||||
ProgressDialog loadDialog(this);
|
ProgressDialog loadDialog(this);
|
||||||
auto update = newInstance->doUpdate();
|
auto update = inst->doUpdate();
|
||||||
connect(update.get(), &Task::failed, [this](QString reason)
|
connect(update.get(), &Task::failed, [this](QString reason)
|
||||||
{
|
{
|
||||||
QString error = QString("Instance load failed: %1").arg(reason);
|
QString error = QString("Instance load failed: %1").arg(reason);
|
||||||
@ -1184,6 +1197,30 @@ void MainWindow::on_actionAddInstance_triggered()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MainWindow::on_actionAddInstance_triggered()
|
||||||
|
{
|
||||||
|
waitForMinecraftVersions();
|
||||||
|
|
||||||
|
NewInstanceDialog newInstDlg(this);
|
||||||
|
if (!newInstDlg.exec())
|
||||||
|
return;
|
||||||
|
|
||||||
|
MMC->settings()->set("LastUsedGroupForNewInstance", newInstDlg.instGroup());
|
||||||
|
|
||||||
|
const QUrl modpackUrl = newInstDlg.modpackUrl();
|
||||||
|
|
||||||
|
|
||||||
|
if (modpackUrl.isValid())
|
||||||
|
{
|
||||||
|
instanceFromZipPack(newInstDlg.instName(), newInstDlg.instGroup(), newInstDlg.iconKey(), modpackUrl);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
instanceFromVersion(newInstDlg.instName(), newInstDlg.instGroup(), newInstDlg.iconKey(), newInstDlg.selectedVersion());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::on_actionCopyInstance_triggered()
|
void MainWindow::on_actionCopyInstance_triggered()
|
||||||
{
|
{
|
||||||
if (!m_selectedInstance)
|
if (!m_selectedInstance)
|
||||||
@ -1389,7 +1426,7 @@ void MainWindow::on_actionMoreNews_triggered()
|
|||||||
|
|
||||||
void MainWindow::newsButtonClicked()
|
void MainWindow::newsButtonClicked()
|
||||||
{
|
{
|
||||||
QList<NewsEntryPtr> entries = MMC->newsChecker()->getNewsEntries();
|
QList<NewsEntryPtr> entries = m_newsChecker->getNewsEntries();
|
||||||
if (entries.count() > 0)
|
if (entries.count() > 0)
|
||||||
openWebPage(QUrl(entries[0]->link));
|
openWebPage(QUrl(entries[0]->link));
|
||||||
else
|
else
|
||||||
@ -1686,19 +1723,15 @@ void MainWindow::launchInstance(InstancePtr instance, AuthSessionPtr session,
|
|||||||
|
|
||||||
QString launchScript;
|
QString launchScript;
|
||||||
|
|
||||||
if (!instance->prepareForLaunch(session, launchScript))
|
BaseProcess *proc = instance->prepareForLaunch(session);
|
||||||
|
if (!proc)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
MinecraftProcess *proc = new MinecraftProcess(instance);
|
|
||||||
proc->setLaunchScript(launchScript);
|
|
||||||
proc->setWorkdir(instance->minecraftRoot());
|
|
||||||
|
|
||||||
this->hide();
|
this->hide();
|
||||||
|
|
||||||
console = new ConsoleWindow(proc);
|
console = new ConsoleWindow(proc);
|
||||||
connect(console, SIGNAL(isClosing()), this, SLOT(instanceEnded()));
|
connect(console, SIGNAL(isClosing()), this, SLOT(instanceEnded()));
|
||||||
|
|
||||||
proc->setLogin(session);
|
|
||||||
proc->arm();
|
proc->arm();
|
||||||
|
|
||||||
if (profiler)
|
if (profiler)
|
||||||
@ -1725,7 +1758,7 @@ void MainWindow::launchInstance(InstancePtr instance, AuthSessionPtr session,
|
|||||||
{
|
{
|
||||||
dialog.accept();
|
dialog.accept();
|
||||||
QMessageBox msg;
|
QMessageBox msg;
|
||||||
msg.setText(tr("The launch of Minecraft itself is delayed until you press the "
|
msg.setText(tr("The game launch is delayed until you press the "
|
||||||
"button. This is the right time to setup the profiler, as the "
|
"button. This is the right time to setup the profiler, as the "
|
||||||
"profiler server is running now.\n\n%1").arg(message));
|
"profiler server is running now.\n\n%1").arg(message));
|
||||||
msg.setWindowTitle(tr("Waiting"));
|
msg.setWindowTitle(tr("Waiting"));
|
||||||
@ -1837,32 +1870,6 @@ void MainWindow::instanceEnded()
|
|||||||
this->show();
|
this->show();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::checkMigrateLegacyAssets()
|
|
||||||
{
|
|
||||||
int legacyAssets = AssetsUtils::findLegacyAssets();
|
|
||||||
if (legacyAssets > 0)
|
|
||||||
{
|
|
||||||
ProgressDialog migrateDlg(this);
|
|
||||||
AssetsMigrateTask migrateTask(legacyAssets, &migrateDlg);
|
|
||||||
{
|
|
||||||
ThreadTask threadTask(&migrateTask);
|
|
||||||
|
|
||||||
if (migrateDlg.exec(&threadTask))
|
|
||||||
{
|
|
||||||
QLOG_INFO() << "Assets migration task completed successfully";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
QLOG_INFO() << "Assets migration task reported failure";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
QLOG_INFO() << "Didn't find any legacy assets to migrate";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::checkSetDefaultJava()
|
void MainWindow::checkSetDefaultJava()
|
||||||
{
|
{
|
||||||
const QString javaHack = "IntelHack";
|
const QString javaHack = "IntelHack";
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#include "logic/auth/MojangAccount.h"
|
#include "logic/auth/MojangAccount.h"
|
||||||
#include "logic/net/NetJob.h"
|
#include "logic/net/NetJob.h"
|
||||||
|
|
||||||
|
class NewsChecker;
|
||||||
class QToolButton;
|
class QToolButton;
|
||||||
class LabeledToolButton;
|
class LabeledToolButton;
|
||||||
class QLabel;
|
class QLabel;
|
||||||
@ -51,7 +52,6 @@ public:
|
|||||||
void openWebPage(QUrl url);
|
void openWebPage(QUrl url);
|
||||||
|
|
||||||
void checkSetDefaultJava();
|
void checkSetDefaultJava();
|
||||||
void checkMigrateLegacyAssets();
|
|
||||||
void checkInstancePathForProblems();
|
void checkInstancePathForProblems();
|
||||||
|
|
||||||
private
|
private
|
||||||
@ -182,6 +182,11 @@ protected:
|
|||||||
|
|
||||||
void setSelectedInstanceById(const QString &id);
|
void setSelectedInstanceById(const QString &id);
|
||||||
|
|
||||||
|
void waitForMinecraftVersions();
|
||||||
|
void instanceFromVersion(QString instName, QString instGroup, QString instIcon, BaseVersionPtr version);
|
||||||
|
void instanceFromZipPack(QString instName, QString instGroup, QString instIcon, QUrl url);
|
||||||
|
void finalizeInstance(InstancePtr inst);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::MainWindow *ui;
|
Ui::MainWindow *ui;
|
||||||
class GroupView *view;
|
class GroupView *view;
|
||||||
@ -194,6 +199,7 @@ private:
|
|||||||
QToolButton *newsLabel;
|
QToolButton *newsLabel;
|
||||||
|
|
||||||
std::shared_ptr<GenericPageProvider> m_globalSettingsProvider;
|
std::shared_ptr<GenericPageProvider> m_globalSettingsProvider;
|
||||||
|
std::shared_ptr<NewsChecker> m_newsChecker;
|
||||||
|
|
||||||
InstancePtr m_selectedInstance;
|
InstancePtr m_selectedInstance;
|
||||||
QString m_currentInstIcon;
|
QString m_currentInstIcon;
|
||||||
|
@ -99,7 +99,7 @@ AboutDialog::AboutDialog(QWidget *parent) : QDialog(parent), ui(new Ui::AboutDia
|
|||||||
|
|
||||||
connect(ui->closeButton, SIGNAL(clicked()), SLOT(close()));
|
connect(ui->closeButton, SIGNAL(clicked()), SLOT(close()));
|
||||||
|
|
||||||
MMC->connect(ui->aboutQt, SIGNAL(clicked()), SLOT(aboutQt()));
|
connect(ui->aboutQt, &QPushButton::clicked, &QApplication::aboutQt);
|
||||||
|
|
||||||
loadPatronList();
|
loadPatronList();
|
||||||
}
|
}
|
||||||
|
@ -7,10 +7,10 @@
|
|||||||
#include <QScrollBar>
|
#include <QScrollBar>
|
||||||
#include <QShortcut>
|
#include <QShortcut>
|
||||||
|
|
||||||
#include "logic/MinecraftProcess.h"
|
#include "logic/BaseProcess.h"
|
||||||
#include "gui/GuiUtil.h"
|
#include "gui/GuiUtil.h"
|
||||||
|
|
||||||
LogPage::LogPage(MinecraftProcess *proc, QWidget *parent)
|
LogPage::LogPage(BaseProcess *proc, QWidget *parent)
|
||||||
: QWidget(parent), ui(new Ui::LogPage), m_process(proc)
|
: QWidget(parent), ui(new Ui::LogPage), m_process(proc)
|
||||||
{
|
{
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
#include "logic/BaseInstance.h"
|
#include "logic/BaseInstance.h"
|
||||||
#include "logic/net/NetJob.h"
|
#include "logic/net/NetJob.h"
|
||||||
#include "logic/MinecraftProcess.h"
|
#include "logic/BaseProcess.h"
|
||||||
#include "BasePage.h"
|
#include "BasePage.h"
|
||||||
#include <MultiMC.h>
|
#include <MultiMC.h>
|
||||||
|
|
||||||
@ -36,7 +36,7 @@ class LogPage : public QWidget, public BasePage
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit LogPage(MinecraftProcess *proc, QWidget *parent = 0);
|
explicit LogPage(BaseProcess *proc, QWidget *parent = 0);
|
||||||
virtual ~LogPage();
|
virtual ~LogPage();
|
||||||
virtual QString displayName() const override
|
virtual QString displayName() const override
|
||||||
{
|
{
|
||||||
@ -78,7 +78,7 @@ private slots:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::LogPage *ui;
|
Ui::LogPage *ui;
|
||||||
MinecraftProcess *m_process;
|
BaseProcess *m_process;
|
||||||
int m_last_scroll_value = 0;
|
int m_last_scroll_value = 0;
|
||||||
bool m_scroll_active = true;
|
bool m_scroll_active = true;
|
||||||
int m_saved_offset = 0;
|
int m_saved_offset = 0;
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
#include "gui/dialogs/ModEditDialogCommon.h"
|
#include "gui/dialogs/ModEditDialogCommon.h"
|
||||||
#include "logic/ModList.h"
|
#include "logic/ModList.h"
|
||||||
#include "logic/Mod.h"
|
#include "logic/Mod.h"
|
||||||
#include "logic/VersionFilterData.h"
|
#include "logic/minecraft/VersionFilterData.h"
|
||||||
|
|
||||||
ModFolderPage::ModFolderPage(BaseInstance *inst, std::shared_ptr<ModList> mods, QString id,
|
ModFolderPage::ModFolderPage(BaseInstance *inst, std::shared_ptr<ModList> mods, QString id,
|
||||||
QString iconName, QString displayName, QString helpPage,
|
QString iconName, QString displayName, QString helpPage,
|
||||||
@ -80,7 +80,7 @@ bool CoreModFolderPage::shouldDisplay() const
|
|||||||
auto inst = dynamic_cast<OneSixInstance *>(m_inst);
|
auto inst = dynamic_cast<OneSixInstance *>(m_inst);
|
||||||
if (!inst)
|
if (!inst)
|
||||||
return true;
|
return true;
|
||||||
auto version = inst->getFullVersion();
|
auto version = inst->getMinecraftProfile();
|
||||||
if (!version)
|
if (!version)
|
||||||
return true;
|
return true;
|
||||||
if (version->m_releaseTime < g_VersionFilterData.legacyCutoffDate)
|
if (version->m_releaseTime < g_VersionFilterData.legacyCutoffDate)
|
||||||
|
@ -21,17 +21,17 @@
|
|||||||
|
|
||||||
#include "gui/GuiUtil.h"
|
#include "gui/GuiUtil.h"
|
||||||
#include "logic/RecursiveFileSystemWatcher.h"
|
#include "logic/RecursiveFileSystemWatcher.h"
|
||||||
#include "logic/BaseInstance.h"
|
#include <pathutils.h>
|
||||||
|
|
||||||
OtherLogsPage::OtherLogsPage(BaseInstance *instance, QWidget *parent)
|
OtherLogsPage::OtherLogsPage(QString path, QWidget *parent)
|
||||||
: QWidget(parent), ui(new Ui::OtherLogsPage), m_instance(instance),
|
: QWidget(parent), ui(new Ui::OtherLogsPage), m_path(path),
|
||||||
m_watcher(new RecursiveFileSystemWatcher(this))
|
m_watcher(new RecursiveFileSystemWatcher(this))
|
||||||
{
|
{
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
ui->tabWidget->tabBar()->hide();
|
ui->tabWidget->tabBar()->hide();
|
||||||
|
|
||||||
m_watcher->setFileExpression("(.*\\.log(\\.[0-9]*)?$)|(crash-.*\\.txt)");
|
m_watcher->setFileExpression("(.*\\.log(\\.[0-9]*)?$)|(crash-.*\\.txt)");
|
||||||
m_watcher->setRootDir(QDir::current().absoluteFilePath(m_instance->minecraftRoot()));
|
m_watcher->setRootDir(QDir::current().absoluteFilePath(m_path));
|
||||||
|
|
||||||
connect(m_watcher, &RecursiveFileSystemWatcher::filesChanged, this,
|
connect(m_watcher, &RecursiveFileSystemWatcher::filesChanged, this,
|
||||||
&OtherLogsPage::populateSelectLogBox);
|
&OtherLogsPage::populateSelectLogBox);
|
||||||
@ -76,7 +76,7 @@ void OtherLogsPage::on_selectLogBox_currentIndexChanged(const int index)
|
|||||||
file = ui->selectLogBox->itemText(index);
|
file = ui->selectLogBox->itemText(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (file.isEmpty() || !QFile::exists(m_instance->minecraftRoot() + "/" + file))
|
if (file.isEmpty() || !QFile::exists(PathCombine(m_path, file)))
|
||||||
{
|
{
|
||||||
m_currentFile = QString();
|
m_currentFile = QString();
|
||||||
ui->text->clear();
|
ui->text->clear();
|
||||||
@ -92,7 +92,7 @@ void OtherLogsPage::on_selectLogBox_currentIndexChanged(const int index)
|
|||||||
|
|
||||||
void OtherLogsPage::on_btnReload_clicked()
|
void OtherLogsPage::on_btnReload_clicked()
|
||||||
{
|
{
|
||||||
QFile file(m_instance->minecraftRoot() + "/" + m_currentFile);
|
QFile file(PathCombine(m_path, m_currentFile));
|
||||||
if (!file.open(QFile::ReadOnly))
|
if (!file.open(QFile::ReadOnly))
|
||||||
{
|
{
|
||||||
setControlsEnabled(false);
|
setControlsEnabled(false);
|
||||||
@ -132,7 +132,7 @@ void OtherLogsPage::on_btnDelete_clicked()
|
|||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
QFile file(m_instance->minecraftRoot() + "/" + m_currentFile);
|
QFile file(PathCombine(m_path, m_currentFile));
|
||||||
if (!file.remove())
|
if (!file.remove())
|
||||||
{
|
{
|
||||||
QMessageBox::critical(this, tr("Error"), tr("Unable to delete %1: %2")
|
QMessageBox::critical(this, tr("Error"), tr("Unable to delete %1: %2")
|
||||||
|
@ -27,14 +27,12 @@ class OtherLogsPage;
|
|||||||
|
|
||||||
class RecursiveFileSystemWatcher;
|
class RecursiveFileSystemWatcher;
|
||||||
|
|
||||||
class BaseInstance;
|
|
||||||
|
|
||||||
class OtherLogsPage : public QWidget, public BasePage
|
class OtherLogsPage : public QWidget, public BasePage
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit OtherLogsPage(BaseInstance *instance, QWidget *parent = 0);
|
explicit OtherLogsPage(QString path, QWidget *parent = 0);
|
||||||
~OtherLogsPage();
|
~OtherLogsPage();
|
||||||
|
|
||||||
QString id() const override
|
QString id() const override
|
||||||
@ -66,7 +64,7 @@ private slots:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::OtherLogsPage *ui;
|
Ui::OtherLogsPage *ui;
|
||||||
BaseInstance *m_instance;
|
QString m_path;
|
||||||
RecursiveFileSystemWatcher *m_watcher;
|
RecursiveFileSystemWatcher *m_watcher;
|
||||||
QString m_currentFile;
|
QString m_currentFile;
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
class ResourcePackPage : public ModFolderPage
|
class ResourcePackPage : public ModFolderPage
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit ResourcePackPage(BaseInstance *instance, QWidget *parent = 0)
|
explicit ResourcePackPage(MinecraftInstance *instance, QWidget *parent = 0)
|
||||||
: ModFolderPage(instance, instance->resourcePackList(), "resourcepacks",
|
: ModFolderPage(instance, instance->resourcePackList(), "resourcepacks",
|
||||||
"resourcepacks", tr("Resource packs"), "Resource-packs", parent)
|
"resourcepacks", tr("Resource packs"), "Resource-packs", parent)
|
||||||
{
|
{
|
||||||
|
@ -209,7 +209,7 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ScreenshotsPage::ScreenshotsPage(BaseInstance *instance, QWidget *parent)
|
ScreenshotsPage::ScreenshotsPage(QString path, QWidget *parent)
|
||||||
: QWidget(parent), ui(new Ui::ScreenshotsPage)
|
: QWidget(parent), ui(new Ui::ScreenshotsPage)
|
||||||
{
|
{
|
||||||
m_model.reset(new QFileSystemModel());
|
m_model.reset(new QFileSystemModel());
|
||||||
@ -219,7 +219,7 @@ ScreenshotsPage::ScreenshotsPage(BaseInstance *instance, QWidget *parent)
|
|||||||
m_model->setReadOnly(false);
|
m_model->setReadOnly(false);
|
||||||
m_model->setNameFilters({"*.png"});
|
m_model->setNameFilters({"*.png"});
|
||||||
m_model->setNameFilterDisables(false);
|
m_model->setNameFilterDisables(false);
|
||||||
m_folder = PathCombine(instance->minecraftRoot(), "screenshots");
|
m_folder = path;
|
||||||
m_valid = ensureFolderPathExists(m_folder);
|
m_valid = ensureFolderPathExists(m_folder);
|
||||||
|
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
@ -37,7 +37,7 @@ class ScreenshotsPage : public QWidget, public BasePage
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit ScreenshotsPage(BaseInstance *instance, QWidget *parent = 0);
|
explicit ScreenshotsPage(QString path, QWidget *parent = 0);
|
||||||
virtual ~ScreenshotsPage();
|
virtual ~ScreenshotsPage();
|
||||||
|
|
||||||
virtual void opened() override;
|
virtual void opened() override;
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
class TexturePackPage : public ModFolderPage
|
class TexturePackPage : public ModFolderPage
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit TexturePackPage(BaseInstance *instance, QWidget *parent = 0)
|
explicit TexturePackPage(MinecraftInstance *instance, QWidget *parent = 0)
|
||||||
: ModFolderPage(instance, instance->texturePackList(), "texturepacks", "resourcepacks",
|
: ModFolderPage(instance, instance->texturePackList(), "texturepacks", "resourcepacks",
|
||||||
tr("Texture packs"), "Texture-packs", parent)
|
tr("Texture packs"), "Texture-packs", parent)
|
||||||
{
|
{
|
||||||
|
@ -38,7 +38,7 @@
|
|||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
|
|
||||||
#include "logic/ModList.h"
|
#include "logic/ModList.h"
|
||||||
#include "logic/minecraft/InstanceVersion.h"
|
#include "logic/minecraft/MinecraftProfile.h"
|
||||||
#include "logic/EnabledItemFilter.h"
|
#include "logic/EnabledItemFilter.h"
|
||||||
#include "logic/forge/ForgeVersionList.h"
|
#include "logic/forge/ForgeVersionList.h"
|
||||||
#include "logic/forge/ForgeInstaller.h"
|
#include "logic/forge/ForgeInstaller.h"
|
||||||
@ -65,7 +65,7 @@ VersionPage::VersionPage(OneSixInstance *inst, QWidget *parent)
|
|||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
ui->tabWidget->tabBar()->hide();
|
ui->tabWidget->tabBar()->hide();
|
||||||
|
|
||||||
m_version = m_inst->getFullVersion();
|
m_version = m_inst->getMinecraftProfile();
|
||||||
if (m_version)
|
if (m_version)
|
||||||
{
|
{
|
||||||
main_model = new EnabledItemFilter(this);
|
main_model = new EnabledItemFilter(this);
|
||||||
@ -109,11 +109,11 @@ void VersionPage::disableVersionControls()
|
|||||||
ui->removeLibraryBtn->setEnabled(false);
|
ui->removeLibraryBtn->setEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VersionPage::reloadInstanceVersion()
|
bool VersionPage::reloadMinecraftProfile()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
m_inst->reloadVersion();
|
m_inst->reloadProfile();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
catch (MMCError &e)
|
catch (MMCError &e)
|
||||||
@ -132,7 +132,7 @@ bool VersionPage::reloadInstanceVersion()
|
|||||||
|
|
||||||
void VersionPage::on_reloadLibrariesBtn_clicked()
|
void VersionPage::on_reloadLibrariesBtn_clicked()
|
||||||
{
|
{
|
||||||
reloadInstanceVersion();
|
reloadMinecraftProfile();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VersionPage::on_removeLibraryBtn_clicked()
|
void VersionPage::on_removeLibraryBtn_clicked()
|
||||||
@ -202,7 +202,7 @@ void VersionPage::on_moveLibraryUpBtn_clicked()
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
const int row = ui->libraryTreeView->selectionModel()->selectedRows().first().row();
|
const int row = ui->libraryTreeView->selectionModel()->selectedRows().first().row();
|
||||||
m_version->move(row, InstanceVersion::MoveUp);
|
m_version->move(row, MinecraftProfile::MoveUp);
|
||||||
}
|
}
|
||||||
catch (MMCError &e)
|
catch (MMCError &e)
|
||||||
{
|
{
|
||||||
@ -219,7 +219,7 @@ void VersionPage::on_moveLibraryDownBtn_clicked()
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
const int row = ui->libraryTreeView->selectionModel()->selectedRows().first().row();
|
const int row = ui->libraryTreeView->selectionModel()->selectedRows().first().row();
|
||||||
m_version->move(row, InstanceVersion::MoveDown);
|
m_version->move(row, MinecraftProfile::MoveDown);
|
||||||
}
|
}
|
||||||
catch (MMCError &e)
|
catch (MMCError &e)
|
||||||
{
|
{
|
||||||
@ -244,7 +244,7 @@ void VersionPage::on_changeMCVersionBtn_clicked()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_inst->versionIsCustom())
|
if (!m_version->isVanilla())
|
||||||
{
|
{
|
||||||
auto result = CustomMessageBox::selectable(
|
auto result = CustomMessageBox::selectable(
|
||||||
this, tr("Are you sure?"),
|
this, tr("Are you sure?"),
|
||||||
@ -256,7 +256,7 @@ void VersionPage::on_changeMCVersionBtn_clicked()
|
|||||||
if (result != QMessageBox::Ok)
|
if (result != QMessageBox::Ok)
|
||||||
return;
|
return;
|
||||||
m_version->revertToVanilla();
|
m_version->revertToVanilla();
|
||||||
reloadInstanceVersion();
|
reloadMinecraftProfile();
|
||||||
}
|
}
|
||||||
m_inst->setIntendedVersionId(vselect.selectedVersion()->descriptor());
|
m_inst->setIntendedVersionId(vselect.selectedVersion()->descriptor());
|
||||||
|
|
||||||
@ -272,31 +272,6 @@ void VersionPage::on_changeMCVersionBtn_clicked()
|
|||||||
|
|
||||||
void VersionPage::on_forgeBtn_clicked()
|
void VersionPage::on_forgeBtn_clicked()
|
||||||
{
|
{
|
||||||
// FIXME: use actual model, not reloading. Move logic to model.
|
|
||||||
if (m_version->hasFtbPack())
|
|
||||||
{
|
|
||||||
if (QMessageBox::question(
|
|
||||||
this, tr("Revert?"),
|
|
||||||
tr("This action will remove the FTB pack version patch. Continue?")) !=
|
|
||||||
QMessageBox::Yes)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
m_version->removeFtbPack();
|
|
||||||
reloadInstanceVersion();
|
|
||||||
}
|
|
||||||
if (m_version->hasDeprecatedVersionFiles())
|
|
||||||
{
|
|
||||||
if (QMessageBox::question(this, tr("Revert?"),
|
|
||||||
tr("This action will remove deprecated version files "
|
|
||||||
"(custom.json and version.json). Continue?")) !=
|
|
||||||
QMessageBox::Yes)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
m_version->removeDeprecatedVersionFiles();
|
|
||||||
reloadInstanceVersion();
|
|
||||||
}
|
|
||||||
VersionSelectDialog vselect(MMC->forgelist().get(), tr("Select Forge version"), this);
|
VersionSelectDialog vselect(MMC->forgelist().get(), tr("Select Forge version"), this);
|
||||||
vselect.setExactFilter(1, m_inst->currentVersionId());
|
vselect.setExactFilter(1, m_inst->currentVersionId());
|
||||||
vselect.setEmptyString(tr("No Forge versions are currently available for Minecraft ") +
|
vselect.setEmptyString(tr("No Forge versions are currently available for Minecraft ") +
|
||||||
@ -311,30 +286,6 @@ void VersionPage::on_forgeBtn_clicked()
|
|||||||
|
|
||||||
void VersionPage::on_liteloaderBtn_clicked()
|
void VersionPage::on_liteloaderBtn_clicked()
|
||||||
{
|
{
|
||||||
if (m_version->hasFtbPack())
|
|
||||||
{
|
|
||||||
if (QMessageBox::question(
|
|
||||||
this, tr("Revert?"),
|
|
||||||
tr("This action will remove the FTB pack version patch. Continue?")) !=
|
|
||||||
QMessageBox::Yes)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
m_version->removeFtbPack();
|
|
||||||
reloadInstanceVersion();
|
|
||||||
}
|
|
||||||
if (m_version->hasDeprecatedVersionFiles())
|
|
||||||
{
|
|
||||||
if (QMessageBox::question(this, tr("Revert?"),
|
|
||||||
tr("This action will remove deprecated version files "
|
|
||||||
"(custom.json and version.json). Continue?")) !=
|
|
||||||
QMessageBox::Yes)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
m_version->removeDeprecatedVersionFiles();
|
|
||||||
reloadInstanceVersion();
|
|
||||||
}
|
|
||||||
VersionSelectDialog vselect(MMC->liteloaderlist().get(), tr("Select LiteLoader version"),
|
VersionSelectDialog vselect(MMC->liteloaderlist().get(), tr("Select LiteLoader version"),
|
||||||
this);
|
this);
|
||||||
vselect.setExactFilter(1, m_inst->currentVersionId());
|
vselect.setExactFilter(1, m_inst->currentVersionId());
|
||||||
@ -364,8 +315,7 @@ void VersionPage::versionCurrent(const QModelIndex ¤t, const QModelIndex &
|
|||||||
ui->moveLibraryUpBtn->setEnabled(enabled);
|
ui->moveLibraryUpBtn->setEnabled(enabled);
|
||||||
}
|
}
|
||||||
QString selectedId = m_version->versionFileId(current.row());
|
QString selectedId = m_version->versionFileId(current.row());
|
||||||
if (selectedId == "net.minecraft" || selectedId == "org.multimc.custom.json" ||
|
if (selectedId == "net.minecraft")
|
||||||
selectedId == "org.multimc.version.json")
|
|
||||||
{
|
{
|
||||||
ui->changeMCVersionBtn->setEnabled(true);
|
ui->changeMCVersionBtn->setEnabled(true);
|
||||||
}
|
}
|
||||||
|
@ -67,11 +67,11 @@ slots:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
/// FIXME: this shouldn't be necessary!
|
/// FIXME: this shouldn't be necessary!
|
||||||
bool reloadInstanceVersion();
|
bool reloadMinecraftProfile();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::VersionPage *ui;
|
Ui::VersionPage *ui;
|
||||||
std::shared_ptr<InstanceVersion> m_version;
|
std::shared_ptr<MinecraftProfile> m_version;
|
||||||
EnabledItemFilter *main_model;
|
EnabledItemFilter *main_model;
|
||||||
OneSixInstance *m_inst;
|
OneSixInstance *m_inst;
|
||||||
NetJobPtr forgeJob;
|
NetJobPtr forgeJob;
|
||||||
|
@ -28,7 +28,6 @@
|
|||||||
#include <cmdutils.h>
|
#include <cmdutils.h>
|
||||||
#include "logic/minecraft/MinecraftVersionList.h"
|
#include "logic/minecraft/MinecraftVersionList.h"
|
||||||
#include "logic/icons/IconList.h"
|
#include "logic/icons/IconList.h"
|
||||||
#include "logic/InstanceList.h"
|
|
||||||
|
|
||||||
BaseInstance::BaseInstance(const QString &rootDir, SettingsObject *settings, QObject *parent)
|
BaseInstance::BaseInstance(const QString &rootDir, SettingsObject *settings, QObject *parent)
|
||||||
: QObject(parent)
|
: QObject(parent)
|
||||||
@ -115,30 +114,9 @@ QString BaseInstance::instanceRoot() const
|
|||||||
return m_rootDir;
|
return m_rootDir;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString BaseInstance::minecraftRoot() const
|
|
||||||
{
|
|
||||||
QFileInfo mcDir(PathCombine(instanceRoot(), "minecraft"));
|
|
||||||
QFileInfo dotMCDir(PathCombine(instanceRoot(), ".minecraft"));
|
|
||||||
|
|
||||||
if (dotMCDir.exists() && !mcDir.exists())
|
|
||||||
return dotMCDir.filePath();
|
|
||||||
else
|
|
||||||
return mcDir.filePath();
|
|
||||||
}
|
|
||||||
|
|
||||||
InstanceList *BaseInstance::instList() const
|
|
||||||
{
|
|
||||||
return qobject_cast<InstanceList *>(parent());
|
|
||||||
}
|
|
||||||
|
|
||||||
InstancePtr BaseInstance::getSharedPtr()
|
InstancePtr BaseInstance::getSharedPtr()
|
||||||
{
|
{
|
||||||
return instList()->getInstanceById(id());
|
return shared_from_this();
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<BaseVersionList> BaseInstance::versionList() const
|
|
||||||
{
|
|
||||||
return MMC->minecraftlist();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SettingsObject &BaseInstance::settings() const
|
SettingsObject &BaseInstance::settings() const
|
||||||
|
@ -24,14 +24,14 @@
|
|||||||
#include "logic/settings/INIFile.h"
|
#include "logic/settings/INIFile.h"
|
||||||
#include "logic/BaseVersionList.h"
|
#include "logic/BaseVersionList.h"
|
||||||
#include "logic/auth/MojangAccount.h"
|
#include "logic/auth/MojangAccount.h"
|
||||||
|
#include "Mod.h"
|
||||||
|
|
||||||
class ModList;
|
class ModList;
|
||||||
class QDialog;
|
class QDialog;
|
||||||
class QDir;
|
class QDir;
|
||||||
class Task;
|
class Task;
|
||||||
class MinecraftProcess;
|
class BaseProcess;
|
||||||
class OneSixUpdate;
|
class OneSixUpdate;
|
||||||
class InstanceList;
|
|
||||||
class BaseInstancePrivate;
|
class BaseInstancePrivate;
|
||||||
|
|
||||||
// pointer for lazy people
|
// pointer for lazy people
|
||||||
@ -46,7 +46,7 @@ typedef std::shared_ptr<BaseInstance> InstancePtr;
|
|||||||
* To create a new instance type, create a new class inheriting from this class
|
* To create a new instance type, create a new class inheriting from this class
|
||||||
* and implement the pure virtual functions.
|
* and implement the pure virtual functions.
|
||||||
*/
|
*/
|
||||||
class BaseInstance : public QObject
|
class BaseInstance : public QObject, public std::enable_shared_from_this<BaseInstance>
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
protected:
|
protected:
|
||||||
@ -57,9 +57,10 @@ public:
|
|||||||
/// virtual destructor to make sure the destruction is COMPLETE
|
/// virtual destructor to make sure the destruction is COMPLETE
|
||||||
virtual ~BaseInstance() {};
|
virtual ~BaseInstance() {};
|
||||||
|
|
||||||
virtual void init() {}
|
|
||||||
virtual void copy(const QDir &newDir) {}
|
virtual void copy(const QDir &newDir) {}
|
||||||
|
|
||||||
|
virtual void init() = 0;
|
||||||
|
|
||||||
/// nuke thoroughly - deletes the instance contents, notifies the list/model which is
|
/// nuke thoroughly - deletes the instance contents, notifies the list/model which is
|
||||||
/// responsible of cleaning up the husk
|
/// responsible of cleaning up the husk
|
||||||
void nuke();
|
void nuke();
|
||||||
@ -77,9 +78,6 @@ public:
|
|||||||
/// Path to the instance's root directory.
|
/// Path to the instance's root directory.
|
||||||
QString instanceRoot() const;
|
QString instanceRoot() const;
|
||||||
|
|
||||||
/// Path to the instance's minecraft directory.
|
|
||||||
QString minecraftRoot() const;
|
|
||||||
|
|
||||||
QString name() const;
|
QString name() const;
|
||||||
void setName(QString val);
|
void setName(QString val);
|
||||||
|
|
||||||
@ -101,8 +99,6 @@ public:
|
|||||||
virtual QString intendedVersionId() const = 0;
|
virtual QString intendedVersionId() const = 0;
|
||||||
virtual bool setIntendedVersionId(QString version) = 0;
|
virtual bool setIntendedVersionId(QString version) = 0;
|
||||||
|
|
||||||
virtual bool versionIsCustom() = 0;
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* The instance's current version.
|
* The instance's current version.
|
||||||
* This value represents the instance's current version. If this value is
|
* This value represents the instance's current version. If this value is
|
||||||
@ -112,21 +108,11 @@ public:
|
|||||||
virtual QString currentVersionId() const = 0;
|
virtual QString currentVersionId() const = 0;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Whether or not Minecraft should be downloaded when the instance is launched.
|
* Whether or not 'the game' should be downloaded when the instance is launched.
|
||||||
*/
|
*/
|
||||||
virtual bool shouldUpdate() const = 0;
|
virtual bool shouldUpdate() const = 0;
|
||||||
virtual void setShouldUpdate(bool val) = 0;
|
virtual void setShouldUpdate(bool val) = 0;
|
||||||
|
|
||||||
////// Mod Lists //////
|
|
||||||
virtual std::shared_ptr<ModList> resourcePackList()
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
virtual std::shared_ptr<ModList> texturePackList()
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Traits. Normally inside the version, depends on instance implementation.
|
/// Traits. Normally inside the version, depends on instance implementation.
|
||||||
virtual QSet <QString> traits() = 0;
|
virtual QSet <QString> traits() = 0;
|
||||||
|
|
||||||
@ -138,21 +124,13 @@ public:
|
|||||||
/// Sets the last launched time to 'val' milliseconds since epoch
|
/// Sets the last launched time to 'val' milliseconds since epoch
|
||||||
void setLastLaunch(qint64 val = QDateTime::currentMSecsSinceEpoch());
|
void setLastLaunch(qint64 val = QDateTime::currentMSecsSinceEpoch());
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Gets the instance list that this instance is a part of.
|
|
||||||
* Returns NULL if this instance is not in a list
|
|
||||||
* (the parent is not an InstanceList).
|
|
||||||
* \return A pointer to the InstanceList containing this instance.
|
|
||||||
*/
|
|
||||||
InstanceList *instList() const;
|
|
||||||
|
|
||||||
InstancePtr getSharedPtr();
|
InstancePtr getSharedPtr();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Gets a pointer to this instance's version list.
|
* \brief Gets a pointer to this instance's version list.
|
||||||
* \return A pointer to the available version list for this instance.
|
* \return A pointer to the available version list for this instance.
|
||||||
*/
|
*/
|
||||||
virtual std::shared_ptr<BaseVersionList> versionList() const;
|
virtual std::shared_ptr<BaseVersionList> versionList() const = 0;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Gets this instance's settings object.
|
* \brief Gets this instance's settings object.
|
||||||
@ -164,8 +142,8 @@ public:
|
|||||||
/// returns a valid update task
|
/// returns a valid update task
|
||||||
virtual std::shared_ptr<Task> doUpdate() = 0;
|
virtual std::shared_ptr<Task> doUpdate() = 0;
|
||||||
|
|
||||||
/// returns a valid minecraft process, ready for launch with the given account.
|
/// returns a valid process, ready for launch with the given account.
|
||||||
virtual bool prepareForLaunch(AuthSessionPtr account, QString & launchScript) = 0;
|
virtual BaseProcess *prepareForLaunch(AuthSessionPtr account) = 0;
|
||||||
|
|
||||||
/// do any necessary cleanups after the instance finishes. also runs before
|
/// do any necessary cleanups after the instance finishes. also runs before
|
||||||
/// 'prepareForLaunch'
|
/// 'prepareForLaunch'
|
||||||
|
@ -14,28 +14,37 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
#include "MultiMC.h"
|
#include "logic/BaseProcess.h"
|
||||||
#include "BuildConfig.h"
|
#include "logger/QsLog.h"
|
||||||
|
|
||||||
#include "MinecraftProcess.h"
|
|
||||||
|
|
||||||
#include <QDataStream>
|
|
||||||
#include <QFile>
|
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QProcessEnvironment>
|
#include <QEventLoop>
|
||||||
#include <QRegularExpression>
|
|
||||||
#include <QStandardPaths>
|
|
||||||
|
|
||||||
#include "BaseInstance.h"
|
MessageLevel::Enum MessageLevel::getLevel(const QString& levelName)
|
||||||
|
{
|
||||||
|
if (levelName == "MultiMC")
|
||||||
|
return MessageLevel::MultiMC;
|
||||||
|
else if (levelName == "Debug")
|
||||||
|
return MessageLevel::Debug;
|
||||||
|
else if (levelName == "Info")
|
||||||
|
return MessageLevel::Info;
|
||||||
|
else if (levelName == "Message")
|
||||||
|
return MessageLevel::Message;
|
||||||
|
else if (levelName == "Warning")
|
||||||
|
return MessageLevel::Warning;
|
||||||
|
else if (levelName == "Error")
|
||||||
|
return MessageLevel::Error;
|
||||||
|
else if (levelName == "Fatal")
|
||||||
|
return MessageLevel::Fatal;
|
||||||
|
// Skip PrePost, it's not exposed to !![]!
|
||||||
|
else
|
||||||
|
return MessageLevel::Message;
|
||||||
|
}
|
||||||
|
|
||||||
#include "osutils.h"
|
BaseProcess::BaseProcess(InstancePtr instance): QProcess(), m_instance(instance)
|
||||||
#include "pathutils.h"
|
{
|
||||||
#include "cmdutils.h"
|
}
|
||||||
|
|
||||||
#define IBUS "@im=ibus"
|
void BaseProcess::init()
|
||||||
|
|
||||||
// constructor
|
|
||||||
MinecraftProcess::MinecraftProcess(InstancePtr inst) : m_instance(inst)
|
|
||||||
{
|
{
|
||||||
connect(this, SIGNAL(finished(int, QProcess::ExitStatus)),
|
connect(this, SIGNAL(finished(int, QProcess::ExitStatus)),
|
||||||
SLOT(finish(int, QProcess::ExitStatus)));
|
SLOT(finish(int, QProcess::ExitStatus)));
|
||||||
@ -113,114 +122,31 @@ MinecraftProcess::MinecraftProcess(InstancePtr inst) : m_instance(inst)
|
|||||||
if (m_instance->settings().get("LogPrePostOutput").toBool())
|
if (m_instance->settings().get("LogPrePostOutput").toBool())
|
||||||
{
|
{
|
||||||
connect(&m_prepostlaunchprocess, &QProcess::readyReadStandardError, this,
|
connect(&m_prepostlaunchprocess, &QProcess::readyReadStandardError, this,
|
||||||
&MinecraftProcess::on_prepost_stdErr);
|
&BaseProcess::on_prepost_stdErr);
|
||||||
connect(&m_prepostlaunchprocess, &QProcess::readyReadStandardOutput, this,
|
connect(&m_prepostlaunchprocess, &QProcess::readyReadStandardOutput, this,
|
||||||
&MinecraftProcess::on_prepost_stdOut);
|
&BaseProcess::on_prepost_stdOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
// a process has been constructed for the instance. It is running from MultiMC POV
|
// a process has been constructed for the instance. It is running from MultiMC POV
|
||||||
m_instance->setRunning(true);
|
m_instance->setRunning(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MinecraftProcess::setWorkdir(QString path)
|
|
||||||
|
void BaseProcess::setWorkdir(QString path)
|
||||||
{
|
{
|
||||||
QDir mcDir(path);
|
QDir mcDir(path);
|
||||||
this->setWorkingDirectory(mcDir.absolutePath());
|
this->setWorkingDirectory(mcDir.absolutePath());
|
||||||
m_prepostlaunchprocess.setWorkingDirectory(mcDir.absolutePath());
|
m_prepostlaunchprocess.setWorkingDirectory(mcDir.absolutePath());
|
||||||
}
|
}
|
||||||
|
|
||||||
QString MinecraftProcess::censorPrivateInfo(QString in)
|
void BaseProcess::logOutput(const QStringList &lines, MessageLevel::Enum defaultLevel,
|
||||||
{
|
|
||||||
if (!m_session)
|
|
||||||
return in;
|
|
||||||
|
|
||||||
if (m_session->session != "-")
|
|
||||||
in.replace(m_session->session, "<SESSION ID>");
|
|
||||||
in.replace(m_session->access_token, "<ACCESS TOKEN>");
|
|
||||||
in.replace(m_session->client_token, "<CLIENT TOKEN>");
|
|
||||||
in.replace(m_session->uuid, "<PROFILE ID>");
|
|
||||||
in.replace(m_session->player_name, "<PROFILE NAME>");
|
|
||||||
|
|
||||||
auto i = m_session->u.properties.begin();
|
|
||||||
while (i != m_session->u.properties.end())
|
|
||||||
{
|
|
||||||
in.replace(i.value(), "<" + i.key().toUpper() + ">");
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
|
|
||||||
return in;
|
|
||||||
}
|
|
||||||
|
|
||||||
// console window
|
|
||||||
MessageLevel::Enum MinecraftProcess::guessLevel(const QString &line, MessageLevel::Enum level)
|
|
||||||
{
|
|
||||||
QRegularExpression re("\\[(?<timestamp>[0-9:]+)\\] \\[[^/]+/(?<level>[^\\]]+)\\]");
|
|
||||||
auto match = re.match(line);
|
|
||||||
if(match.hasMatch())
|
|
||||||
{
|
|
||||||
// New style logs from log4j
|
|
||||||
QString timestamp = match.captured("timestamp");
|
|
||||||
QString levelStr = match.captured("level");
|
|
||||||
if(levelStr == "INFO")
|
|
||||||
level = MessageLevel::Message;
|
|
||||||
if(levelStr == "WARN")
|
|
||||||
level = MessageLevel::Warning;
|
|
||||||
if(levelStr == "ERROR")
|
|
||||||
level = MessageLevel::Error;
|
|
||||||
if(levelStr == "FATAL")
|
|
||||||
level = MessageLevel::Fatal;
|
|
||||||
if(levelStr == "TRACE" || levelStr == "DEBUG")
|
|
||||||
level = MessageLevel::Debug;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Old style forge logs
|
|
||||||
if (line.contains("[INFO]") || line.contains("[CONFIG]") || line.contains("[FINE]") ||
|
|
||||||
line.contains("[FINER]") || line.contains("[FINEST]"))
|
|
||||||
level = MessageLevel::Message;
|
|
||||||
if (line.contains("[SEVERE]") || line.contains("[STDERR]"))
|
|
||||||
level = MessageLevel::Error;
|
|
||||||
if (line.contains("[WARNING]"))
|
|
||||||
level = MessageLevel::Warning;
|
|
||||||
if (line.contains("[DEBUG]"))
|
|
||||||
level = MessageLevel::Debug;
|
|
||||||
}
|
|
||||||
if (line.contains("overwriting existing"))
|
|
||||||
return MessageLevel::Fatal;
|
|
||||||
if (line.contains("Exception in thread") || line.contains(QRegularExpression("\\s+at ")))
|
|
||||||
return MessageLevel::Error;
|
|
||||||
return level;
|
|
||||||
}
|
|
||||||
|
|
||||||
MessageLevel::Enum MinecraftProcess::getLevel(const QString &levelName)
|
|
||||||
{
|
|
||||||
if (levelName == "MultiMC")
|
|
||||||
return MessageLevel::MultiMC;
|
|
||||||
else if (levelName == "Debug")
|
|
||||||
return MessageLevel::Debug;
|
|
||||||
else if (levelName == "Info")
|
|
||||||
return MessageLevel::Info;
|
|
||||||
else if (levelName == "Message")
|
|
||||||
return MessageLevel::Message;
|
|
||||||
else if (levelName == "Warning")
|
|
||||||
return MessageLevel::Warning;
|
|
||||||
else if (levelName == "Error")
|
|
||||||
return MessageLevel::Error;
|
|
||||||
else if (levelName == "Fatal")
|
|
||||||
return MessageLevel::Fatal;
|
|
||||||
// Skip PrePost, it's not exposed to !![]!
|
|
||||||
else
|
|
||||||
return MessageLevel::Message;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MinecraftProcess::logOutput(const QStringList &lines, MessageLevel::Enum defaultLevel,
|
|
||||||
bool guessLevel, bool censor)
|
bool guessLevel, bool censor)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < lines.size(); ++i)
|
for (int i = 0; i < lines.size(); ++i)
|
||||||
logOutput(lines[i], defaultLevel, guessLevel, censor);
|
logOutput(lines[i], defaultLevel, guessLevel, censor);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MinecraftProcess::logOutput(QString line, MessageLevel::Enum defaultLevel, bool guessLevel,
|
void BaseProcess::logOutput(QString line, MessageLevel::Enum defaultLevel, bool guessLevel,
|
||||||
bool censor)
|
bool censor)
|
||||||
{
|
{
|
||||||
MessageLevel::Enum level = defaultLevel;
|
MessageLevel::Enum level = defaultLevel;
|
||||||
@ -235,7 +161,7 @@ void MinecraftProcess::logOutput(QString line, MessageLevel::Enum defaultLevel,
|
|||||||
int endmark = line.indexOf("]!");
|
int endmark = line.indexOf("]!");
|
||||||
if (line.startsWith("!![") && endmark != -1)
|
if (line.startsWith("!![") && endmark != -1)
|
||||||
{
|
{
|
||||||
level = getLevel(line.left(endmark).mid(3));
|
level = MessageLevel::getLevel(line.left(endmark).mid(3));
|
||||||
line = line.mid(endmark + 2);
|
line = line.mid(endmark + 2);
|
||||||
}
|
}
|
||||||
// Guess level
|
// Guess level
|
||||||
@ -248,7 +174,7 @@ void MinecraftProcess::logOutput(QString line, MessageLevel::Enum defaultLevel,
|
|||||||
emit log(line, level);
|
emit log(line, level);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MinecraftProcess::on_stdErr()
|
void BaseProcess::on_stdErr()
|
||||||
{
|
{
|
||||||
QByteArray data = readAllStandardError();
|
QByteArray data = readAllStandardError();
|
||||||
QString str = m_err_leftover + QString::fromLocal8Bit(data);
|
QString str = m_err_leftover + QString::fromLocal8Bit(data);
|
||||||
@ -260,7 +186,7 @@ void MinecraftProcess::on_stdErr()
|
|||||||
logOutput(lines, MessageLevel::Error);
|
logOutput(lines, MessageLevel::Error);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MinecraftProcess::on_stdOut()
|
void BaseProcess::on_stdOut()
|
||||||
{
|
{
|
||||||
QByteArray data = readAllStandardOutput();
|
QByteArray data = readAllStandardOutput();
|
||||||
QString str = m_out_leftover + QString::fromLocal8Bit(data);
|
QString str = m_out_leftover + QString::fromLocal8Bit(data);
|
||||||
@ -272,7 +198,7 @@ void MinecraftProcess::on_stdOut()
|
|||||||
logOutput(lines);
|
logOutput(lines);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MinecraftProcess::on_prepost_stdErr()
|
void BaseProcess::on_prepost_stdErr()
|
||||||
{
|
{
|
||||||
QByteArray data = m_prepostlaunchprocess.readAllStandardError();
|
QByteArray data = m_prepostlaunchprocess.readAllStandardError();
|
||||||
QString str = m_err_leftover + QString::fromLocal8Bit(data);
|
QString str = m_err_leftover + QString::fromLocal8Bit(data);
|
||||||
@ -284,7 +210,7 @@ void MinecraftProcess::on_prepost_stdErr()
|
|||||||
logOutput(lines, MessageLevel::PrePost, false, false);
|
logOutput(lines, MessageLevel::PrePost, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MinecraftProcess::on_prepost_stdOut()
|
void BaseProcess::on_prepost_stdOut()
|
||||||
{
|
{
|
||||||
QByteArray data = m_prepostlaunchprocess.readAllStandardOutput();
|
QByteArray data = m_prepostlaunchprocess.readAllStandardOutput();
|
||||||
QString str = m_out_leftover + QString::fromLocal8Bit(data);
|
QString str = m_out_leftover + QString::fromLocal8Bit(data);
|
||||||
@ -297,7 +223,7 @@ void MinecraftProcess::on_prepost_stdOut()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// exit handler
|
// exit handler
|
||||||
void MinecraftProcess::finish(int code, ExitStatus status)
|
void BaseProcess::finish(int code, ExitStatus status)
|
||||||
{
|
{
|
||||||
// Flush console window
|
// Flush console window
|
||||||
if (!m_err_leftover.isEmpty())
|
if (!m_err_leftover.isEmpty())
|
||||||
@ -316,18 +242,18 @@ void MinecraftProcess::finish(int code, ExitStatus status)
|
|||||||
if (status == NormalExit)
|
if (status == NormalExit)
|
||||||
{
|
{
|
||||||
//: Message displayed on instance exit
|
//: Message displayed on instance exit
|
||||||
emit log(tr("Minecraft exited with exitcode %1.").arg(code));
|
emit log(tr("Game exited with exitcode %1.").arg(code));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//: Message displayed on instance crashed
|
//: Message displayed on instance crashed
|
||||||
emit log(tr("Minecraft crashed with exitcode %1.").arg(code));
|
emit log(tr("Game crashed with exitcode %1.").arg(code));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//: Message displayed after the instance exits due to kill request
|
//: Message displayed after the instance exits due to kill request
|
||||||
emit log(tr("Minecraft was killed by user."), MessageLevel::Error);
|
emit log(tr("Game was killed by user."), MessageLevel::Error);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_prepostlaunchprocess.processEnvironment().insert("INST_EXITCODE", QString(code));
|
m_prepostlaunchprocess.processEnvironment().insert("INST_EXITCODE", QString(code));
|
||||||
@ -340,7 +266,7 @@ void MinecraftProcess::finish(int code, ExitStatus status)
|
|||||||
emit ended(m_instance, code, status);
|
emit ended(m_instance, code, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MinecraftProcess::killMinecraft()
|
void BaseProcess::killProcess()
|
||||||
{
|
{
|
||||||
killed = true;
|
killed = true;
|
||||||
if (m_prepostlaunchprocess.state() == QProcess::Running)
|
if (m_prepostlaunchprocess.state() == QProcess::Running)
|
||||||
@ -353,7 +279,7 @@ void MinecraftProcess::killMinecraft()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MinecraftProcess::preLaunch()
|
bool BaseProcess::preLaunch()
|
||||||
{
|
{
|
||||||
QString prelaunch_cmd = m_instance->settings().get("PreLaunchCommand").toString();
|
QString prelaunch_cmd = m_instance->settings().get("PreLaunchCommand").toString();
|
||||||
if (!prelaunch_cmd.isEmpty())
|
if (!prelaunch_cmd.isEmpty())
|
||||||
@ -398,7 +324,7 @@ bool MinecraftProcess::preLaunch()
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool MinecraftProcess::postLaunch()
|
bool BaseProcess::postLaunch()
|
||||||
{
|
{
|
||||||
QString postlaunch_cmd = m_instance->settings().get("PostExitCommand").toString();
|
QString postlaunch_cmd = m_instance->settings().get("PostExitCommand").toString();
|
||||||
if (!postlaunch_cmd.isEmpty())
|
if (!postlaunch_cmd.isEmpty())
|
||||||
@ -439,7 +365,7 @@ bool MinecraftProcess::postLaunch()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MinecraftProcess::waitForPrePost()
|
bool BaseProcess::waitForPrePost()
|
||||||
{
|
{
|
||||||
if (!m_prepostlaunchprocess.waitForStarted())
|
if (!m_prepostlaunchprocess.waitForStarted())
|
||||||
return false;
|
return false;
|
||||||
@ -457,18 +383,7 @@ bool MinecraftProcess::waitForPrePost()
|
|||||||
return ret == 0;
|
return ret == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
QMap<QString, QString> MinecraftProcess::getVariables() const
|
QString BaseProcess::substituteVariables(const QString &cmd) const
|
||||||
{
|
|
||||||
QMap<QString, QString> out;
|
|
||||||
out.insert("INST_NAME", m_instance->name());
|
|
||||||
out.insert("INST_ID", m_instance->id());
|
|
||||||
out.insert("INST_DIR", QDir(m_instance->instanceRoot()).absolutePath());
|
|
||||||
out.insert("INST_MC_DIR", QDir(m_instance->minecraftRoot()).absolutePath());
|
|
||||||
out.insert("INST_JAVA", m_instance->settings().get("JavaPath").toString());
|
|
||||||
out.insert("INST_JAVA_ARGS", javaArguments().join(' '));
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
QString MinecraftProcess::substituteVariables(const QString &cmd) const
|
|
||||||
{
|
{
|
||||||
QString out = cmd;
|
QString out = cmd;
|
||||||
auto variables = getVariables();
|
auto variables = getVariables();
|
||||||
@ -483,96 +398,3 @@ QString MinecraftProcess::substituteVariables(const QString &cmd) const
|
|||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList MinecraftProcess::javaArguments() const
|
|
||||||
{
|
|
||||||
QStringList args;
|
|
||||||
|
|
||||||
// custom args go first. we want to override them if we have our own here.
|
|
||||||
args.append(m_instance->extraArguments());
|
|
||||||
|
|
||||||
// OSX dock icon and name
|
|
||||||
#ifdef OSX
|
|
||||||
args << "-Xdock:icon=icon.png";
|
|
||||||
args << QString("-Xdock:name=\"%1\"").arg(m_instance->windowTitle());
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// HACK: Stupid hack for Intel drivers. See: https://mojang.atlassian.net/browse/MCL-767
|
|
||||||
#ifdef Q_OS_WIN32
|
|
||||||
args << QString("-XX:HeapDumpPath=MojangTricksIntelDriversForPerformance_javaw.exe_"
|
|
||||||
"minecraft.exe.heapdump");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
args << QString("-Xms%1m").arg(m_instance->settings().get("MinMemAlloc").toInt());
|
|
||||||
args << QString("-Xmx%1m").arg(m_instance->settings().get("MaxMemAlloc").toInt());
|
|
||||||
auto permgen = m_instance->settings().get("PermGen").toInt();
|
|
||||||
if (permgen != 64)
|
|
||||||
{
|
|
||||||
args << QString("-XX:PermSize=%1m").arg(permgen);
|
|
||||||
}
|
|
||||||
args << "-Duser.language=en";
|
|
||||||
if (!m_nativeFolder.isEmpty())
|
|
||||||
args << QString("-Djava.library.path=%1").arg(m_nativeFolder);
|
|
||||||
args << "-jar" << PathCombine(MMC->bin(), "jars", "NewLaunch.jar");
|
|
||||||
|
|
||||||
return args;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MinecraftProcess::arm()
|
|
||||||
{
|
|
||||||
emit log("MultiMC version: " + BuildConfig.printableVersionString() + "\n\n");
|
|
||||||
emit log("Minecraft folder is:\n" + workingDirectory() + "\n\n");
|
|
||||||
|
|
||||||
if (!preLaunch())
|
|
||||||
{
|
|
||||||
emit ended(m_instance, 1, QProcess::CrashExit);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_instance->setLastLaunch();
|
|
||||||
|
|
||||||
QStringList args = javaArguments();
|
|
||||||
|
|
||||||
QString JavaPath = m_instance->settings().get("JavaPath").toString();
|
|
||||||
emit log("Java path is:\n" + JavaPath + "\n\n");
|
|
||||||
QString allArgs = args.join(", ");
|
|
||||||
emit log("Java Arguments:\n[" + censorPrivateInfo(allArgs) + "]\n\n");
|
|
||||||
|
|
||||||
auto realJavaPath = QStandardPaths::findExecutable(JavaPath);
|
|
||||||
if (realJavaPath.isEmpty())
|
|
||||||
{
|
|
||||||
emit log(tr("The java binary \"%1\" couldn't be found. You may have to set up java "
|
|
||||||
"if Minecraft fails to launch.").arg(JavaPath),
|
|
||||||
MessageLevel::Warning);
|
|
||||||
}
|
|
||||||
|
|
||||||
// instantiate the launcher part
|
|
||||||
start(JavaPath, args);
|
|
||||||
if (!waitForStarted())
|
|
||||||
{
|
|
||||||
//: Error message displayed if instace can't start
|
|
||||||
emit log(tr("Could not launch minecraft!"), MessageLevel::Error);
|
|
||||||
m_instance->cleanupAfterRun();
|
|
||||||
emit launch_failed(m_instance);
|
|
||||||
// not running, failed
|
|
||||||
m_instance->setRunning(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// send the launch script to the launcher part
|
|
||||||
QByteArray bytes = launchScript.toUtf8();
|
|
||||||
writeData(bytes.constData(), bytes.length());
|
|
||||||
}
|
|
||||||
|
|
||||||
void MinecraftProcess::launch()
|
|
||||||
{
|
|
||||||
QString launchString("launch\n");
|
|
||||||
QByteArray bytes = launchString.toUtf8();
|
|
||||||
writeData(bytes.constData(), bytes.length());
|
|
||||||
}
|
|
||||||
|
|
||||||
void MinecraftProcess::abort()
|
|
||||||
{
|
|
||||||
QString launchString("abort\n");
|
|
||||||
QByteArray bytes = launchString.toUtf8();
|
|
||||||
writeData(bytes.constData(), bytes.length());
|
|
||||||
}
|
|
@ -16,9 +16,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QProcess>
|
#include <QProcess>
|
||||||
#include <QString>
|
|
||||||
#include "BaseInstance.h"
|
#include "BaseInstance.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -38,41 +36,18 @@ enum Enum
|
|||||||
Fatal, /**< Fatal Errors */
|
Fatal, /**< Fatal Errors */
|
||||||
PrePost, /**< Pre/Post Launch command output */
|
PrePost, /**< Pre/Post Launch command output */
|
||||||
};
|
};
|
||||||
|
MessageLevel::Enum getLevel(const QString &levelName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
class BaseProcess: public QProcess
|
||||||
* @file data/minecraftprocess.h
|
|
||||||
* @brief The MinecraftProcess class
|
|
||||||
*/
|
|
||||||
class MinecraftProcess : public QProcess
|
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
protected:
|
||||||
/**
|
explicit BaseProcess(InstancePtr instance);
|
||||||
* @brief MinecraftProcess constructor
|
void init();
|
||||||
* @param inst the Instance pointer to launch
|
|
||||||
*/
|
|
||||||
MinecraftProcess(InstancePtr inst);
|
|
||||||
|
|
||||||
virtual ~MinecraftProcess()
|
public: /* methods */
|
||||||
{
|
virtual ~BaseProcess() {};
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief start the launcher part with the provided launch script
|
|
||||||
*/
|
|
||||||
void arm();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief launch the armed instance!
|
|
||||||
*/
|
|
||||||
void launch();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief abort launch!
|
|
||||||
*/
|
|
||||||
void abort();
|
|
||||||
|
|
||||||
InstancePtr instance()
|
InstancePtr instance()
|
||||||
{
|
{
|
||||||
@ -81,26 +56,36 @@ public:
|
|||||||
|
|
||||||
void setWorkdir(QString path);
|
void setWorkdir(QString path);
|
||||||
|
|
||||||
void setLaunchScript(QString script)
|
void killProcess();
|
||||||
{
|
|
||||||
launchScript = script;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setNativeFolder(QString natives)
|
/**
|
||||||
{
|
* @brief prepare the process for launch (for multi-stage launch)
|
||||||
m_nativeFolder = natives;
|
*/
|
||||||
}
|
virtual void arm() = 0;
|
||||||
|
|
||||||
void killMinecraft();
|
/**
|
||||||
|
* @brief launch the armed instance
|
||||||
|
*/
|
||||||
|
virtual void launch() = 0;
|
||||||
|
|
||||||
inline void setLogin(AuthSessionPtr session)
|
/**
|
||||||
{
|
* @brief abort launch
|
||||||
m_session = session;
|
*/
|
||||||
}
|
virtual void abort() = 0;
|
||||||
|
|
||||||
|
protected: /* methods */
|
||||||
|
bool preLaunch();
|
||||||
|
bool postLaunch();
|
||||||
|
bool waitForPrePost();
|
||||||
|
QString substituteVariables(const QString &cmd) const;
|
||||||
|
|
||||||
|
virtual QMap<QString, QString> getVariables() const = 0;
|
||||||
|
virtual QString censorPrivateInfo(QString in) = 0;
|
||||||
|
virtual MessageLevel::Enum guessLevel(const QString &message, MessageLevel::Enum defaultLevel) = 0;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
/**
|
/**
|
||||||
* @brief emitted when Minecraft immediately fails to run
|
* @brief emitted when the Process immediately fails to run
|
||||||
*/
|
*/
|
||||||
void launch_failed(InstancePtr);
|
void launch_failed(InstancePtr);
|
||||||
|
|
||||||
@ -115,7 +100,7 @@ signals:
|
|||||||
void postlaunch_failed(InstancePtr, int code, QProcess::ExitStatus status);
|
void postlaunch_failed(InstancePtr, int code, QProcess::ExitStatus status);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief emitted when mc has finished and the PostLaunchCommand was run
|
* @brief emitted when the process has finished and the PostLaunchCommand was run
|
||||||
*/
|
*/
|
||||||
void ended(InstancePtr, int code, QProcess::ExitStatus status);
|
void ended(InstancePtr, int code, QProcess::ExitStatus status);
|
||||||
|
|
||||||
@ -126,26 +111,7 @@ signals:
|
|||||||
*/
|
*/
|
||||||
void log(QString text, MessageLevel::Enum level = MessageLevel::MultiMC);
|
void log(QString text, MessageLevel::Enum level = MessageLevel::MultiMC);
|
||||||
|
|
||||||
protected:
|
protected slots:
|
||||||
InstancePtr m_instance;
|
|
||||||
QString m_err_leftover;
|
|
||||||
QString m_out_leftover;
|
|
||||||
QProcess m_prepostlaunchprocess;
|
|
||||||
bool killed = false;
|
|
||||||
AuthSessionPtr m_session;
|
|
||||||
QString launchScript;
|
|
||||||
QString m_nativeFolder;
|
|
||||||
|
|
||||||
bool preLaunch();
|
|
||||||
bool postLaunch();
|
|
||||||
bool waitForPrePost();
|
|
||||||
QMap<QString, QString> getVariables() const;
|
|
||||||
QString substituteVariables(const QString &cmd) const;
|
|
||||||
|
|
||||||
QStringList javaArguments() const;
|
|
||||||
|
|
||||||
protected
|
|
||||||
slots:
|
|
||||||
void finish(int, QProcess::ExitStatus status);
|
void finish(int, QProcess::ExitStatus status);
|
||||||
void on_stdErr();
|
void on_stdErr();
|
||||||
void on_stdOut();
|
void on_stdOut();
|
||||||
@ -158,8 +124,10 @@ slots:
|
|||||||
MessageLevel::Enum defaultLevel = MessageLevel::Message,
|
MessageLevel::Enum defaultLevel = MessageLevel::Message,
|
||||||
bool guessLevel = true, bool censor = true);
|
bool guessLevel = true, bool censor = true);
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
QString censorPrivateInfo(QString in);
|
InstancePtr m_instance;
|
||||||
MessageLevel::Enum guessLevel(const QString &message, MessageLevel::Enum defaultLevel);
|
QString m_err_leftover;
|
||||||
MessageLevel::Enum getLevel(const QString &levelName);
|
QString m_out_leftover;
|
||||||
|
QProcess m_prepostlaunchprocess;
|
||||||
|
bool killed = false;
|
||||||
};
|
};
|
@ -27,12 +27,13 @@
|
|||||||
|
|
||||||
#include "logic/BaseInstance.h"
|
#include "logic/BaseInstance.h"
|
||||||
#include "logic/LegacyInstance.h"
|
#include "logic/LegacyInstance.h"
|
||||||
#include "logic/LegacyFTBInstance.h"
|
|
||||||
#include "logic/OneSixInstance.h"
|
#include "logic/OneSixInstance.h"
|
||||||
#include "logic/OneSixFTBInstance.h"
|
|
||||||
#include "logic/OneSixInstance.h"
|
#include "logic/OneSixInstance.h"
|
||||||
#include "logic/BaseVersion.h"
|
#include "logic/BaseVersion.h"
|
||||||
#include "logic/minecraft/MinecraftVersion.h"
|
#include "logic/minecraft/MinecraftVersion.h"
|
||||||
|
#include "logic/ftb/LegacyFTBInstance.h"
|
||||||
|
#include "logic/ftb/OneSixFTBInstance.h"
|
||||||
|
#include "logic/ftb/FTBVersion.h"
|
||||||
|
|
||||||
InstanceFactory InstanceFactory::loader;
|
InstanceFactory InstanceFactory::loader;
|
||||||
|
|
||||||
@ -74,8 +75,8 @@ InstanceFactory::InstLoadError InstanceFactory::loadInstance(InstancePtr &inst,
|
|||||||
return NoLoadError;
|
return NoLoadError;
|
||||||
}
|
}
|
||||||
|
|
||||||
InstanceFactory::InstCreateError InstanceFactory::createInstance(InstancePtr &inst, BaseVersionPtr version,
|
InstanceFactory::InstCreateError
|
||||||
const QString &instDir, const InstanceFactory::InstType type)
|
InstanceFactory::createInstance(InstancePtr &inst, BaseVersionPtr version, const QString &instDir)
|
||||||
{
|
{
|
||||||
QDir rootDir(instDir);
|
QDir rootDir(instDir);
|
||||||
|
|
||||||
@ -85,8 +86,8 @@ InstanceFactory::InstCreateError InstanceFactory::createInstance(InstancePtr &in
|
|||||||
QLOG_ERROR() << "Can't create instance folder" << instDir;
|
QLOG_ERROR() << "Can't create instance folder" << instDir;
|
||||||
return InstanceFactory::CantCreateDir;
|
return InstanceFactory::CantCreateDir;
|
||||||
}
|
}
|
||||||
auto mcVer = std::dynamic_pointer_cast<MinecraftVersion>(version);
|
|
||||||
if (!mcVer)
|
if (!version)
|
||||||
{
|
{
|
||||||
QLOG_ERROR() << "Can't create instance for non-existing MC version";
|
QLOG_ERROR() << "Can't create instance for non-existing MC version";
|
||||||
return InstanceFactory::NoSuchVersion;
|
return InstanceFactory::NoSuchVersion;
|
||||||
@ -95,39 +96,39 @@ InstanceFactory::InstCreateError InstanceFactory::createInstance(InstancePtr &in
|
|||||||
auto m_settings = new INISettingsObject(PathCombine(instDir, "instance.cfg"));
|
auto m_settings = new INISettingsObject(PathCombine(instDir, "instance.cfg"));
|
||||||
m_settings->registerSetting("InstanceType", "Legacy");
|
m_settings->registerSetting("InstanceType", "Legacy");
|
||||||
|
|
||||||
if (type == NormalInst)
|
auto minecraftVersion = std::dynamic_pointer_cast<MinecraftVersion>(version);
|
||||||
|
if(minecraftVersion)
|
||||||
{
|
{
|
||||||
|
auto mcVer = std::dynamic_pointer_cast<MinecraftVersion>(version);
|
||||||
m_settings->set("InstanceType", "OneSix");
|
m_settings->set("InstanceType", "OneSix");
|
||||||
inst.reset(new OneSixInstance(instDir, m_settings));
|
inst.reset(new OneSixInstance(instDir, m_settings));
|
||||||
inst->setIntendedVersionId(version->descriptor());
|
inst->setIntendedVersionId(version->descriptor());
|
||||||
|
inst->init();
|
||||||
|
return InstanceFactory::NoCreateError;
|
||||||
}
|
}
|
||||||
else if (type == FTBInstance)
|
auto ftbVersion = std::dynamic_pointer_cast<FTBVersion>(version);
|
||||||
|
if(ftbVersion)
|
||||||
{
|
{
|
||||||
if(mcVer->usesLegacyLauncher())
|
auto mcversion = ftbVersion->getMinecraftVersion();
|
||||||
|
if (mcversion->usesLegacyLauncher())
|
||||||
{
|
{
|
||||||
m_settings->set("InstanceType", "LegacyFTB");
|
m_settings->set("InstanceType", "LegacyFTB");
|
||||||
inst.reset(new LegacyFTBInstance(instDir, m_settings));
|
inst.reset(new LegacyFTBInstance(instDir, m_settings));
|
||||||
inst->setIntendedVersionId(version->descriptor());
|
inst->setIntendedVersionId(mcversion->descriptor());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_settings->set("InstanceType", "OneSixFTB");
|
m_settings->set("InstanceType", "OneSixFTB");
|
||||||
inst.reset(new OneSixFTBInstance(instDir, m_settings));
|
inst.reset(new OneSixFTBInstance(instDir, m_settings));
|
||||||
inst->setIntendedVersionId(version->descriptor());
|
inst->setIntendedVersionId(mcversion->descriptor());
|
||||||
|
inst->init();
|
||||||
}
|
}
|
||||||
|
return InstanceFactory::NoCreateError;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
delete m_settings;
|
delete m_settings;
|
||||||
return InstanceFactory::NoSuchVersion;
|
return InstanceFactory::NoSuchVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
inst->init();
|
|
||||||
|
|
||||||
// FIXME: really, how do you even know?
|
|
||||||
return InstanceFactory::NoCreateError;
|
|
||||||
}
|
|
||||||
|
|
||||||
InstanceFactory::InstCreateError InstanceFactory::copyInstance(InstancePtr &newInstance,
|
InstanceFactory::InstCreateError InstanceFactory::copyInstance(InstancePtr &newInstance,
|
||||||
InstancePtr &oldInstance,
|
InstancePtr &oldInstance,
|
||||||
const QString &instDir)
|
const QString &instDir)
|
||||||
|
@ -56,12 +56,6 @@ public:
|
|||||||
CantCreateDir
|
CantCreateDir
|
||||||
};
|
};
|
||||||
|
|
||||||
enum InstType
|
|
||||||
{
|
|
||||||
NormalInst,
|
|
||||||
FTBInstance
|
|
||||||
};
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Creates a stub instance
|
* \brief Creates a stub instance
|
||||||
*
|
*
|
||||||
@ -74,7 +68,7 @@ public:
|
|||||||
* - CantCreateDir if the given instance directory cannot be created.
|
* - CantCreateDir if the given instance directory cannot be created.
|
||||||
*/
|
*/
|
||||||
InstCreateError createInstance(InstancePtr &inst, BaseVersionPtr version,
|
InstCreateError createInstance(InstancePtr &inst, BaseVersionPtr version,
|
||||||
const QString &instDir, const InstType type = NormalInst);
|
const QString &instDir);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Creates a copy of an existing instance with a new name
|
* \brief Creates a copy of an existing instance with a new name
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#include "logic/minecraft/MinecraftVersionList.h"
|
#include "logic/minecraft/MinecraftVersionList.h"
|
||||||
#include "logic/BaseInstance.h"
|
#include "logic/BaseInstance.h"
|
||||||
#include "logic/InstanceFactory.h"
|
#include "logic/InstanceFactory.h"
|
||||||
|
#include "ftb/FTBVersion.h"
|
||||||
#include "logger/QsLog.h"
|
#include "logger/QsLog.h"
|
||||||
#include "gui/groupview/GroupView.h"
|
#include "gui/groupview/GroupView.h"
|
||||||
|
|
||||||
@ -403,16 +404,16 @@ void InstanceList::loadFTBInstances(QMap<QString, QString> &groupMap,
|
|||||||
QLOG_INFO() << "Converting " << record.name << " as new.";
|
QLOG_INFO() << "Converting " << record.name << " as new.";
|
||||||
InstancePtr instPtr;
|
InstancePtr instPtr;
|
||||||
auto &factory = InstanceFactory::get();
|
auto &factory = InstanceFactory::get();
|
||||||
auto version = MMC->minecraftlist()->findVersion(record.mcVersion);
|
auto mcVersion = std::dynamic_pointer_cast<MinecraftVersion>(MMC->minecraftlist()->findVersion(record.mcVersion));
|
||||||
if (!version)
|
if (!mcVersion)
|
||||||
{
|
{
|
||||||
QLOG_ERROR() << "Can't load instance " << record.instanceDir
|
QLOG_ERROR() << "Can't load instance " << record.instanceDir
|
||||||
<< " because minecraft version " << record.mcVersion
|
<< " because minecraft version " << record.mcVersion
|
||||||
<< " can't be resolved.";
|
<< " can't be resolved.";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
auto error = factory.createInstance(instPtr, version, record.instanceDir,
|
auto ftbVersion = std::make_shared<FTBVersion>(mcVersion);
|
||||||
InstanceFactory::FTBInstance);
|
auto error = factory.createInstance(instPtr, ftbVersion, record.instanceDir);
|
||||||
|
|
||||||
if (!instPtr || error != InstanceFactory::NoCreateError)
|
if (!instPtr || error != InstanceFactory::NoCreateError)
|
||||||
continue;
|
continue;
|
||||||
|
@ -19,7 +19,6 @@
|
|||||||
#include <QAbstractListModel>
|
#include <QAbstractListModel>
|
||||||
#include <QSet>
|
#include <QSet>
|
||||||
#include <gui/groupview/GroupedProxyModel.h>
|
#include <gui/groupview/GroupedProxyModel.h>
|
||||||
#include <QIcon>
|
|
||||||
|
|
||||||
#include "logic/BaseInstance.h"
|
#include "logic/BaseInstance.h"
|
||||||
|
|
||||||
@ -55,7 +54,7 @@ private:
|
|||||||
QSet<FTBRecord> discoverFTBInstances();
|
QSet<FTBRecord> discoverFTBInstances();
|
||||||
void loadFTBInstances(QMap<QString, QString> &groupMap, QList<InstancePtr> & tempList);
|
void loadFTBInstances(QMap<QString, QString> &groupMap, QList<InstancePtr> & tempList);
|
||||||
|
|
||||||
private
|
public
|
||||||
slots:
|
slots:
|
||||||
void saveGroupList();
|
void saveGroupList();
|
||||||
|
|
||||||
|
@ -30,7 +30,6 @@ bool mergeZipFiles(QuaZip *into, QFileInfo from, QSet<QString> &contained,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
contained.insert(filename);
|
contained.insert(filename);
|
||||||
QLOG_INFO() << "Adding file " << filename << " from " << from.fileName();
|
|
||||||
|
|
||||||
if (!fileInsideMod.open(QIODevice::ReadOnly))
|
if (!fileInsideMod.open(QIODevice::ReadOnly))
|
||||||
{
|
{
|
||||||
@ -103,8 +102,6 @@ bool createModdedJar(QString sourceJarPath, QString targetJarPath, const QList<M
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
addedFiles.insert(filename.fileName());
|
addedFiles.insert(filename.fileName());
|
||||||
QLOG_INFO() << "Adding file " << filename.fileName() << " from "
|
|
||||||
<< filename.absoluteFilePath();
|
|
||||||
}
|
}
|
||||||
else if (mod.type() == Mod::MOD_FOLDER)
|
else if (mod.type() == Mod::MOD_FOLDER)
|
||||||
{
|
{
|
||||||
|
@ -24,9 +24,9 @@
|
|||||||
|
|
||||||
#include "LegacyInstance.h"
|
#include "LegacyInstance.h"
|
||||||
|
|
||||||
#include "logic/MinecraftProcess.h"
|
|
||||||
#include "logic/LegacyUpdate.h"
|
#include "logic/LegacyUpdate.h"
|
||||||
#include "logic/icons/IconList.h"
|
#include "logic/icons/IconList.h"
|
||||||
|
#include "logic/minecraft/MinecraftProcess.h"
|
||||||
#include "gui/pages/LegacyUpgradePage.h"
|
#include "gui/pages/LegacyUpgradePage.h"
|
||||||
#include "gui/pages/ModFolderPage.h"
|
#include "gui/pages/ModFolderPage.h"
|
||||||
#include "gui/pages/LegacyJarModPage.h"
|
#include "gui/pages/LegacyJarModPage.h"
|
||||||
@ -36,7 +36,7 @@
|
|||||||
#include <gui/pages/ScreenshotsPage.h>
|
#include <gui/pages/ScreenshotsPage.h>
|
||||||
|
|
||||||
LegacyInstance::LegacyInstance(const QString &rootDir, SettingsObject *settings, QObject *parent)
|
LegacyInstance::LegacyInstance(const QString &rootDir, SettingsObject *settings, QObject *parent)
|
||||||
: BaseInstance(rootDir, settings, parent)
|
: MinecraftInstance(rootDir, settings, parent)
|
||||||
{
|
{
|
||||||
settings->registerSetting("NeedsRebuild", true);
|
settings->registerSetting("NeedsRebuild", true);
|
||||||
settings->registerSetting("ShouldUpdate", false);
|
settings->registerSetting("ShouldUpdate", false);
|
||||||
@ -66,7 +66,7 @@ QList<BasePage *> LegacyInstance::getPages()
|
|||||||
"Loader-mods"));
|
"Loader-mods"));
|
||||||
values.append(new TexturePackPage(this));
|
values.append(new TexturePackPage(this));
|
||||||
values.append(new NotesPage(this));
|
values.append(new NotesPage(this));
|
||||||
values.append(new ScreenshotsPage(this));
|
values.append(new ScreenshotsPage(PathCombine(minecraftRoot(), "screenshots")));
|
||||||
values.append(new InstanceSettingsPage(this));
|
values.append(new InstanceSettingsPage(this));
|
||||||
return values;
|
return values;
|
||||||
}
|
}
|
||||||
@ -124,8 +124,9 @@ std::shared_ptr<Task> LegacyInstance::doUpdate()
|
|||||||
return std::shared_ptr<Task>(new LegacyUpdate(this, this));
|
return std::shared_ptr<Task>(new LegacyUpdate(this, this));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LegacyInstance::prepareForLaunch(AuthSessionPtr account, QString &launchScript)
|
BaseProcess *LegacyInstance::prepareForLaunch(AuthSessionPtr account)
|
||||||
{
|
{
|
||||||
|
QString launchScript;
|
||||||
QIcon icon = MMC->icons()->getIcon(iconKey());
|
QIcon icon = MMC->icons()->getIcon(iconKey());
|
||||||
auto pixmap = icon.pixmap(128, 128);
|
auto pixmap = icon.pixmap(128, 128);
|
||||||
pixmap.save(PathCombine(minecraftRoot(), "icon.png"), "PNG");
|
pixmap.save(PathCombine(minecraftRoot(), "icon.png"), "PNG");
|
||||||
@ -150,7 +151,11 @@ bool LegacyInstance::prepareForLaunch(AuthSessionPtr account, QString &launchScr
|
|||||||
launchScript += "lwjgl " + lwjgl + "\n";
|
launchScript += "lwjgl " + lwjgl + "\n";
|
||||||
launchScript += "launcher legacy\n";
|
launchScript += "launcher legacy\n";
|
||||||
}
|
}
|
||||||
return true;
|
auto process = MinecraftProcess::create(std::dynamic_pointer_cast<MinecraftInstance>(getSharedPtr()));
|
||||||
|
process->setLaunchScript(launchScript);
|
||||||
|
process->setWorkdir(minecraftRoot());
|
||||||
|
process->setLogin(account);
|
||||||
|
return process;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LegacyInstance::cleanupAfterRun()
|
void LegacyInstance::cleanupAfterRun()
|
||||||
@ -158,7 +163,7 @@ void LegacyInstance::cleanupAfterRun()
|
|||||||
// FIXME: delete the launcher and icons and whatnot.
|
// FIXME: delete the launcher and icons and whatnot.
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<ModList> LegacyInstance::coreModList()
|
std::shared_ptr<ModList> LegacyInstance::coreModList() const
|
||||||
{
|
{
|
||||||
if (!core_mod_list)
|
if (!core_mod_list)
|
||||||
{
|
{
|
||||||
@ -168,7 +173,7 @@ std::shared_ptr<ModList> LegacyInstance::coreModList()
|
|||||||
return core_mod_list;
|
return core_mod_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<ModList> LegacyInstance::jarModList()
|
std::shared_ptr<ModList> LegacyInstance::jarModList() const
|
||||||
{
|
{
|
||||||
if (!jar_mod_list)
|
if (!jar_mod_list)
|
||||||
{
|
{
|
||||||
@ -180,13 +185,18 @@ std::shared_ptr<ModList> LegacyInstance::jarModList()
|
|||||||
return jar_mod_list;
|
return jar_mod_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QList<Mod> LegacyInstance::getJarMods() const
|
||||||
|
{
|
||||||
|
return jarModList()->allMods();
|
||||||
|
}
|
||||||
|
|
||||||
void LegacyInstance::jarModsChanged()
|
void LegacyInstance::jarModsChanged()
|
||||||
{
|
{
|
||||||
QLOG_INFO() << "Jar mods of instance " << name() << " have changed. Jar will be rebuilt.";
|
QLOG_INFO() << "Jar mods of instance " << name() << " have changed. Jar will be rebuilt.";
|
||||||
setShouldRebuild(true);
|
setShouldRebuild(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<ModList> LegacyInstance::loaderModList()
|
std::shared_ptr<ModList> LegacyInstance::loaderModList() const
|
||||||
{
|
{
|
||||||
if (!loader_mod_list)
|
if (!loader_mod_list)
|
||||||
{
|
{
|
||||||
@ -196,7 +206,7 @@ std::shared_ptr<ModList> LegacyInstance::loaderModList()
|
|||||||
return loader_mod_list;
|
return loader_mod_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<ModList> LegacyInstance::texturePackList()
|
std::shared_ptr<ModList> LegacyInstance::texturePackList() const
|
||||||
{
|
{
|
||||||
if (!texture_pack_list)
|
if (!texture_pack_list)
|
||||||
{
|
{
|
||||||
|
@ -15,13 +15,13 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "BaseInstance.h"
|
#include "logic/minecraft/MinecraftInstance.h"
|
||||||
#include "gui/pages/BasePageProvider.h"
|
#include "gui/pages/BasePageProvider.h"
|
||||||
|
|
||||||
class ModList;
|
class ModList;
|
||||||
class Task;
|
class Task;
|
||||||
|
|
||||||
class LegacyInstance : public BaseInstance, public BasePageProvider
|
class LegacyInstance : public MinecraftInstance, public BasePageProvider
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
@ -29,6 +29,8 @@ public:
|
|||||||
explicit LegacyInstance(const QString &rootDir, SettingsObject *settings,
|
explicit LegacyInstance(const QString &rootDir, SettingsObject *settings,
|
||||||
QObject *parent = 0);
|
QObject *parent = 0);
|
||||||
|
|
||||||
|
virtual void init() {};
|
||||||
|
|
||||||
/// Path to the instance's minecraft.jar
|
/// Path to the instance's minecraft.jar
|
||||||
QString runnableJar() const;
|
QString runnableJar() const;
|
||||||
|
|
||||||
@ -40,10 +42,11 @@ public:
|
|||||||
virtual QString dialogTitle();
|
virtual QString dialogTitle();
|
||||||
|
|
||||||
////// Mod Lists //////
|
////// Mod Lists //////
|
||||||
std::shared_ptr<ModList> jarModList();
|
std::shared_ptr<ModList> jarModList() const ;
|
||||||
std::shared_ptr<ModList> coreModList();
|
virtual QList< Mod > getJarMods() const override;
|
||||||
std::shared_ptr<ModList> loaderModList();
|
std::shared_ptr<ModList> coreModList() const;
|
||||||
std::shared_ptr<ModList> texturePackList();
|
std::shared_ptr<ModList> loaderModList() const;
|
||||||
|
std::shared_ptr<ModList> texturePackList() const override;
|
||||||
|
|
||||||
////// Directories //////
|
////// Directories //////
|
||||||
QString libDir() const;
|
QString libDir() const;
|
||||||
@ -94,12 +97,6 @@ public:
|
|||||||
|
|
||||||
virtual QString intendedVersionId() const override;
|
virtual QString intendedVersionId() const override;
|
||||||
virtual bool setIntendedVersionId(QString version) override;
|
virtual bool setIntendedVersionId(QString version) override;
|
||||||
// the `version' of Legacy instances is defined by the launcher code.
|
|
||||||
// in contrast with OneSix, where `version' is described in a json file
|
|
||||||
virtual bool versionIsCustom() override
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual QSet<QString> traits()
|
virtual QSet<QString> traits()
|
||||||
{
|
{
|
||||||
@ -110,16 +107,16 @@ public:
|
|||||||
virtual void setShouldUpdate(bool val) override;
|
virtual void setShouldUpdate(bool val) override;
|
||||||
virtual std::shared_ptr<Task> doUpdate() override;
|
virtual std::shared_ptr<Task> doUpdate() override;
|
||||||
|
|
||||||
virtual bool prepareForLaunch(AuthSessionPtr account, QString & launchScript) override;
|
virtual BaseProcess *prepareForLaunch(AuthSessionPtr account) override;
|
||||||
virtual void cleanupAfterRun() override;
|
virtual void cleanupAfterRun() override;
|
||||||
|
|
||||||
virtual QString getStatusbarDescription() override;
|
virtual QString getStatusbarDescription() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::shared_ptr<ModList> jar_mod_list;
|
mutable std::shared_ptr<ModList> jar_mod_list;
|
||||||
std::shared_ptr<ModList> core_mod_list;
|
mutable std::shared_ptr<ModList> core_mod_list;
|
||||||
std::shared_ptr<ModList> loader_mod_list;
|
mutable std::shared_ptr<ModList> loader_mod_list;
|
||||||
std::shared_ptr<ModList> texture_pack_list;
|
mutable std::shared_ptr<ModList> texture_pack_list;
|
||||||
|
|
||||||
protected
|
protected
|
||||||
slots:
|
slots:
|
||||||
|
@ -409,7 +409,7 @@ void LegacyUpdate::ModTheJar()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get the mod list
|
// Get the mod list
|
||||||
auto modList = inst->jarModList();
|
auto modList = inst->getJarMods();
|
||||||
|
|
||||||
QFileInfo runnableJar(inst->runnableJar());
|
QFileInfo runnableJar(inst->runnableJar());
|
||||||
QFileInfo baseJar(inst->baseJar());
|
QFileInfo baseJar(inst->baseJar());
|
||||||
@ -421,7 +421,7 @@ void LegacyUpdate::ModTheJar()
|
|||||||
// yes, this can happen if the instance only has the runnable jar and not the base jar
|
// yes, this can happen if the instance only has the runnable jar and not the base jar
|
||||||
// it *could* be assumed that such an instance is vanilla, but that wouldn't be safe
|
// it *could* be assumed that such an instance is vanilla, but that wouldn't be safe
|
||||||
// because that's not something mmc4 guarantees
|
// because that's not something mmc4 guarantees
|
||||||
if (runnableJar.isFile() && !baseJar.exists() && modList->empty())
|
if (runnableJar.isFile() && !baseJar.exists() && modList.empty())
|
||||||
{
|
{
|
||||||
inst->setShouldRebuild(false);
|
inst->setShouldRebuild(false);
|
||||||
emitSucceeded();
|
emitSucceeded();
|
||||||
@ -452,14 +452,12 @@ void LegacyUpdate::ModTheJar()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TaskStep(); // STEP 1
|
|
||||||
setStatus(tr("Installing mods: Opening minecraft.jar ..."));
|
setStatus(tr("Installing mods: Opening minecraft.jar ..."));
|
||||||
|
|
||||||
const auto & mods = modList->allMods();
|
|
||||||
QString outputJarPath = runnableJar.filePath();
|
QString outputJarPath = runnableJar.filePath();
|
||||||
QString inputJarPath = baseJar.filePath();
|
QString inputJarPath = baseJar.filePath();
|
||||||
|
|
||||||
if(!JarUtils::createModdedJar(inputJarPath, outputJarPath, mods))
|
if(!JarUtils::createModdedJar(inputJarPath, outputJarPath, modList))
|
||||||
{
|
{
|
||||||
emitFailed(tr("Failed to create the custom Minecraft jar file."));
|
emitFailed(tr("Failed to create the custom Minecraft jar file."));
|
||||||
return;
|
return;
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
#include "logic/net/NetJob.h"
|
#include "logic/net/NetJob.h"
|
||||||
#include "logic/tasks/Task.h"
|
#include "logic/tasks/Task.h"
|
||||||
#include "logic/VersionFilterData.h"
|
#include "logic/minecraft/VersionFilterData.h"
|
||||||
|
|
||||||
class MinecraftVersion;
|
class MinecraftVersion;
|
||||||
class BaseInstance;
|
class BaseInstance;
|
||||||
|
@ -22,12 +22,13 @@
|
|||||||
#include "logic/OneSixInstance.h"
|
#include "logic/OneSixInstance.h"
|
||||||
|
|
||||||
#include "logic/OneSixUpdate.h"
|
#include "logic/OneSixUpdate.h"
|
||||||
#include "logic/minecraft/InstanceVersion.h"
|
#include "logic/minecraft/MinecraftProfile.h"
|
||||||
#include "minecraft/VersionBuildError.h"
|
#include "minecraft/VersionBuildError.h"
|
||||||
|
#include "logic/minecraft/MinecraftProcess.h"
|
||||||
|
#include "minecraft/OneSixProfileStrategy.h"
|
||||||
|
|
||||||
#include "logic/assets/AssetsUtils.h"
|
#include "logic/assets/AssetsUtils.h"
|
||||||
#include "icons/IconList.h"
|
#include "logic/icons/IconList.h"
|
||||||
#include "logic/MinecraftProcess.h"
|
|
||||||
#include "gui/pagedialog/PageDialog.h"
|
#include "gui/pagedialog/PageDialog.h"
|
||||||
#include "gui/pages/VersionPage.h"
|
#include "gui/pages/VersionPage.h"
|
||||||
#include "gui/pages/ModFolderPage.h"
|
#include "gui/pages/ModFolderPage.h"
|
||||||
@ -39,24 +40,22 @@
|
|||||||
#include "gui/pages/OtherLogsPage.h"
|
#include "gui/pages/OtherLogsPage.h"
|
||||||
|
|
||||||
OneSixInstance::OneSixInstance(const QString &rootDir, SettingsObject *settings, QObject *parent)
|
OneSixInstance::OneSixInstance(const QString &rootDir, SettingsObject *settings, QObject *parent)
|
||||||
: BaseInstance(rootDir, settings, parent)
|
: MinecraftInstance(rootDir, settings, parent)
|
||||||
{
|
{
|
||||||
m_settings->registerSetting("IntendedVersion", "");
|
m_settings->registerSetting("IntendedVersion", "");
|
||||||
version.reset(new InstanceVersion(this, this));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OneSixInstance::init()
|
void OneSixInstance::init()
|
||||||
{
|
{
|
||||||
try
|
createProfile();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OneSixInstance::createProfile()
|
||||||
{
|
{
|
||||||
reloadVersion();
|
m_version.reset(new MinecraftProfile(new OneSixProfileStrategy(this)));
|
||||||
}
|
|
||||||
catch (MMCError &e)
|
|
||||||
{
|
|
||||||
QLOG_ERROR() << "Caught exception on instance init: " << e.cause();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
QList<BasePage *> OneSixInstance::getPages()
|
QList<BasePage *> OneSixInstance::getPages()
|
||||||
{
|
{
|
||||||
QList<BasePage *> values;
|
QList<BasePage *> values;
|
||||||
@ -68,9 +67,9 @@ QList<BasePage *> OneSixInstance::getPages()
|
|||||||
values.append(new ResourcePackPage(this));
|
values.append(new ResourcePackPage(this));
|
||||||
values.append(new TexturePackPage(this));
|
values.append(new TexturePackPage(this));
|
||||||
values.append(new NotesPage(this));
|
values.append(new NotesPage(this));
|
||||||
values.append(new ScreenshotsPage(this));
|
values.append(new ScreenshotsPage(PathCombine(minecraftRoot(), "screenshots")));
|
||||||
values.append(new InstanceSettingsPage(this));
|
values.append(new InstanceSettingsPage(this));
|
||||||
values.append(new OtherLogsPage(this));
|
values.append(new OtherLogsPage(minecraftRoot()));
|
||||||
return values;
|
return values;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,7 +80,7 @@ QString OneSixInstance::dialogTitle()
|
|||||||
|
|
||||||
QSet<QString> OneSixInstance::traits()
|
QSet<QString> OneSixInstance::traits()
|
||||||
{
|
{
|
||||||
auto version = getFullVersion();
|
auto version = getMinecraftProfile();
|
||||||
if (!version)
|
if (!version)
|
||||||
{
|
{
|
||||||
return {"version-incomplete"};
|
return {"version-incomplete"};
|
||||||
@ -119,70 +118,10 @@ QString replaceTokensIn(QString text, QMap<QString, QString> with)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
QDir OneSixInstance::reconstructAssets(std::shared_ptr<InstanceVersion> version)
|
|
||||||
{
|
|
||||||
QDir assetsDir = QDir("assets/");
|
|
||||||
QDir indexDir = QDir(PathCombine(assetsDir.path(), "indexes"));
|
|
||||||
QDir objectDir = QDir(PathCombine(assetsDir.path(), "objects"));
|
|
||||||
QDir virtualDir = QDir(PathCombine(assetsDir.path(), "virtual"));
|
|
||||||
|
|
||||||
QString indexPath = PathCombine(indexDir.path(), version->assets + ".json");
|
|
||||||
QFile indexFile(indexPath);
|
|
||||||
QDir virtualRoot(PathCombine(virtualDir.path(), version->assets));
|
|
||||||
|
|
||||||
if (!indexFile.exists())
|
|
||||||
{
|
|
||||||
QLOG_ERROR() << "No assets index file" << indexPath << "; can't reconstruct assets";
|
|
||||||
return virtualRoot;
|
|
||||||
}
|
|
||||||
|
|
||||||
QLOG_DEBUG() << "reconstructAssets" << assetsDir.path() << indexDir.path()
|
|
||||||
<< objectDir.path() << virtualDir.path() << virtualRoot.path();
|
|
||||||
|
|
||||||
AssetsIndex index;
|
|
||||||
bool loadAssetsIndex = AssetsUtils::loadAssetsIndexJson(indexPath, &index);
|
|
||||||
|
|
||||||
if (loadAssetsIndex && index.isVirtual)
|
|
||||||
{
|
|
||||||
QLOG_INFO() << "Reconstructing virtual assets folder at" << virtualRoot.path();
|
|
||||||
|
|
||||||
for (QString map : index.objects.keys())
|
|
||||||
{
|
|
||||||
AssetObject asset_object = index.objects.value(map);
|
|
||||||
QString target_path = PathCombine(virtualRoot.path(), map);
|
|
||||||
QFile target(target_path);
|
|
||||||
|
|
||||||
QString tlk = asset_object.hash.left(2);
|
|
||||||
|
|
||||||
QString original_path =
|
|
||||||
PathCombine(PathCombine(objectDir.path(), tlk), asset_object.hash);
|
|
||||||
QFile original(original_path);
|
|
||||||
if (!original.exists())
|
|
||||||
continue;
|
|
||||||
if (!target.exists())
|
|
||||||
{
|
|
||||||
QFileInfo info(target_path);
|
|
||||||
QDir target_dir = info.dir();
|
|
||||||
// QLOG_DEBUG() << target_dir;
|
|
||||||
if (!target_dir.exists())
|
|
||||||
QDir("").mkpath(target_dir.path());
|
|
||||||
|
|
||||||
bool couldCopy = original.copy(target_path);
|
|
||||||
QLOG_DEBUG() << " Copying" << original_path << "to" << target_path
|
|
||||||
<< QString::number(couldCopy); // << original.errorString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Write last used time to virtualRoot/.lastused
|
|
||||||
}
|
|
||||||
|
|
||||||
return virtualRoot;
|
|
||||||
}
|
|
||||||
|
|
||||||
QStringList OneSixInstance::processMinecraftArgs(AuthSessionPtr session)
|
QStringList OneSixInstance::processMinecraftArgs(AuthSessionPtr session)
|
||||||
{
|
{
|
||||||
QString args_pattern = version->minecraftArguments;
|
QString args_pattern = m_version->minecraftArguments;
|
||||||
for (auto tweaker : version->tweakers)
|
for (auto tweaker : m_version->tweakers)
|
||||||
{
|
{
|
||||||
args_pattern += " --tweakClass " + tweaker;
|
args_pattern += " --tweakClass " + tweaker;
|
||||||
}
|
}
|
||||||
@ -197,18 +136,18 @@ QStringList OneSixInstance::processMinecraftArgs(AuthSessionPtr session)
|
|||||||
|
|
||||||
// these do nothing and are stupid.
|
// these do nothing and are stupid.
|
||||||
token_mapping["profile_name"] = name();
|
token_mapping["profile_name"] = name();
|
||||||
token_mapping["version_name"] = version->id;
|
token_mapping["version_name"] = m_version->id;
|
||||||
|
|
||||||
QString absRootDir = QDir(minecraftRoot()).absolutePath();
|
QString absRootDir = QDir(minecraftRoot()).absolutePath();
|
||||||
token_mapping["game_directory"] = absRootDir;
|
token_mapping["game_directory"] = absRootDir;
|
||||||
QString absAssetsDir = QDir("assets/").absolutePath();
|
QString absAssetsDir = QDir("assets/").absolutePath();
|
||||||
token_mapping["game_assets"] = reconstructAssets(version).absolutePath();
|
token_mapping["game_assets"] = AssetsUtils::reconstructAssets(m_version->assets).absolutePath();
|
||||||
|
|
||||||
token_mapping["user_properties"] = session->serializeUserProperties();
|
token_mapping["user_properties"] = session->serializeUserProperties();
|
||||||
token_mapping["user_type"] = session->user_type;
|
token_mapping["user_type"] = session->user_type;
|
||||||
// 1.7.3+ assets tokens
|
// 1.7.3+ assets tokens
|
||||||
token_mapping["assets_root"] = absAssetsDir;
|
token_mapping["assets_root"] = absAssetsDir;
|
||||||
token_mapping["assets_index_name"] = version->assets;
|
token_mapping["assets_index_name"] = m_version->assets;
|
||||||
|
|
||||||
QStringList parts = args_pattern.split(' ', QString::SkipEmptyParts);
|
QStringList parts = args_pattern.split(' ', QString::SkipEmptyParts);
|
||||||
for (int i = 0; i < parts.length(); i++)
|
for (int i = 0; i < parts.length(); i++)
|
||||||
@ -218,40 +157,41 @@ QStringList OneSixInstance::processMinecraftArgs(AuthSessionPtr session)
|
|||||||
return parts;
|
return parts;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OneSixInstance::prepareForLaunch(AuthSessionPtr session, QString &launchScript)
|
BaseProcess *OneSixInstance::prepareForLaunch(AuthSessionPtr session)
|
||||||
{
|
{
|
||||||
|
QString launchScript;
|
||||||
QIcon icon = MMC->icons()->getIcon(iconKey());
|
QIcon icon = MMC->icons()->getIcon(iconKey());
|
||||||
auto pixmap = icon.pixmap(128, 128);
|
auto pixmap = icon.pixmap(128, 128);
|
||||||
pixmap.save(PathCombine(minecraftRoot(), "icon.png"), "PNG");
|
pixmap.save(PathCombine(minecraftRoot(), "icon.png"), "PNG");
|
||||||
|
|
||||||
if (!version)
|
if (!m_version)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
// libraries and class path.
|
// libraries and class path.
|
||||||
{
|
{
|
||||||
auto libs = version->getActiveNormalLibs();
|
auto libs = m_version->getActiveNormalLibs();
|
||||||
for (auto lib : libs)
|
for (auto lib : libs)
|
||||||
{
|
{
|
||||||
launchScript += "cp " + librariesPath().absoluteFilePath(lib->storagePath()) + "\n";
|
launchScript += "cp " + librariesPath().absoluteFilePath(lib->storagePath()) + "\n";
|
||||||
}
|
}
|
||||||
if (version->hasJarMods())
|
auto jarMods = getJarMods();
|
||||||
|
if (!jarMods.isEmpty())
|
||||||
{
|
{
|
||||||
launchScript += "cp " + QDir(instanceRoot()).absoluteFilePath("temp.jar") + "\n";
|
launchScript += "cp " + QDir(instanceRoot()).absoluteFilePath("temp.jar") + "\n";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
QString relpath = version->id + "/" + version->id + ".jar";
|
QString relpath = m_version->id + "/" + m_version->id + ".jar";
|
||||||
launchScript += "cp " + versionsPath().absoluteFilePath(relpath) + "\n";
|
launchScript += "cp " + versionsPath().absoluteFilePath(relpath) + "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!version->mainClass.isEmpty())
|
if (!m_version->mainClass.isEmpty())
|
||||||
{
|
{
|
||||||
launchScript += "mainClass " + version->mainClass + "\n";
|
launchScript += "mainClass " + m_version->mainClass + "\n";
|
||||||
}
|
}
|
||||||
if (!version->appletClass.isEmpty())
|
if (!m_version->appletClass.isEmpty())
|
||||||
{
|
{
|
||||||
launchScript += "appletClass " + version->appletClass + "\n";
|
launchScript += "appletClass " + m_version->appletClass + "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
// generic minecraft params
|
// generic minecraft params
|
||||||
@ -282,7 +222,7 @@ bool OneSixInstance::prepareForLaunch(AuthSessionPtr session, QString &launchScr
|
|||||||
// native libraries (mostly LWJGL)
|
// native libraries (mostly LWJGL)
|
||||||
{
|
{
|
||||||
QDir natives_dir(PathCombine(instanceRoot(), "natives/"));
|
QDir natives_dir(PathCombine(instanceRoot(), "natives/"));
|
||||||
for (auto native : version->getActiveNativeLibs())
|
for (auto native : m_version->getActiveNativeLibs())
|
||||||
{
|
{
|
||||||
QFileInfo finfo(PathCombine("libraries", native->storagePath()));
|
QFileInfo finfo(PathCombine("libraries", native->storagePath()));
|
||||||
launchScript += "ext " + finfo.absoluteFilePath() + "\n";
|
launchScript += "ext " + finfo.absoluteFilePath() + "\n";
|
||||||
@ -291,12 +231,17 @@ bool OneSixInstance::prepareForLaunch(AuthSessionPtr session, QString &launchScr
|
|||||||
}
|
}
|
||||||
|
|
||||||
// traits. including legacyLaunch and others ;)
|
// traits. including legacyLaunch and others ;)
|
||||||
for (auto trait : version->traits)
|
for (auto trait : m_version->traits)
|
||||||
{
|
{
|
||||||
launchScript += "traits " + trait + "\n";
|
launchScript += "traits " + trait + "\n";
|
||||||
}
|
}
|
||||||
launchScript += "launcher onesix\n";
|
launchScript += "launcher onesix\n";
|
||||||
return true;
|
|
||||||
|
auto process = MinecraftProcess::create(std::dynamic_pointer_cast<MinecraftInstance>(getSharedPtr()));
|
||||||
|
process->setLaunchScript(launchScript);
|
||||||
|
process->setWorkdir(minecraftRoot());
|
||||||
|
process->setLogin(session);
|
||||||
|
return process;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OneSixInstance::cleanupAfterRun()
|
void OneSixInstance::cleanupAfterRun()
|
||||||
@ -306,54 +251,68 @@ void OneSixInstance::cleanupAfterRun()
|
|||||||
dir.removeRecursively();
|
dir.removeRecursively();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<ModList> OneSixInstance::loaderModList()
|
std::shared_ptr<ModList> OneSixInstance::loaderModList() const
|
||||||
{
|
{
|
||||||
if (!loader_mod_list)
|
if (!m_loader_mod_list)
|
||||||
{
|
{
|
||||||
loader_mod_list.reset(new ModList(loaderModsDir()));
|
m_loader_mod_list.reset(new ModList(loaderModsDir()));
|
||||||
}
|
}
|
||||||
loader_mod_list->update();
|
m_loader_mod_list->update();
|
||||||
return loader_mod_list;
|
return m_loader_mod_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<ModList> OneSixInstance::coreModList()
|
std::shared_ptr<ModList> OneSixInstance::coreModList() const
|
||||||
{
|
{
|
||||||
if (!core_mod_list)
|
if (!m_core_mod_list)
|
||||||
{
|
{
|
||||||
core_mod_list.reset(new ModList(coreModsDir()));
|
m_core_mod_list.reset(new ModList(coreModsDir()));
|
||||||
}
|
}
|
||||||
core_mod_list->update();
|
m_core_mod_list->update();
|
||||||
return core_mod_list;
|
return m_core_mod_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<ModList> OneSixInstance::resourcePackList()
|
std::shared_ptr<ModList> OneSixInstance::resourcePackList() const
|
||||||
{
|
{
|
||||||
if (!resource_pack_list)
|
if (!m_resource_pack_list)
|
||||||
{
|
{
|
||||||
resource_pack_list.reset(new ModList(resourcePacksDir()));
|
m_resource_pack_list.reset(new ModList(resourcePacksDir()));
|
||||||
}
|
}
|
||||||
resource_pack_list->update();
|
m_resource_pack_list->update();
|
||||||
return resource_pack_list;
|
return m_resource_pack_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<ModList> OneSixInstance::texturePackList()
|
std::shared_ptr<ModList> OneSixInstance::texturePackList() const
|
||||||
{
|
{
|
||||||
if (!texture_pack_list)
|
if (!m_texture_pack_list)
|
||||||
{
|
{
|
||||||
texture_pack_list.reset(new ModList(texturePacksDir()));
|
m_texture_pack_list.reset(new ModList(texturePacksDir()));
|
||||||
}
|
}
|
||||||
texture_pack_list->update();
|
m_texture_pack_list->update();
|
||||||
return texture_pack_list;
|
return m_texture_pack_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OneSixInstance::setIntendedVersionId(QString version)
|
bool OneSixInstance::setIntendedVersionId(QString version)
|
||||||
{
|
{
|
||||||
settings().set("IntendedVersion", version);
|
settings().set("IntendedVersion", version);
|
||||||
QFile::remove(PathCombine(instanceRoot(), "version.json"));
|
if(getMinecraftProfile())
|
||||||
clearVersion();
|
{
|
||||||
|
clearProfile();
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QList< Mod > OneSixInstance::getJarMods() const
|
||||||
|
{
|
||||||
|
QList<Mod> mods;
|
||||||
|
for (auto jarmod : m_version->jarMods)
|
||||||
|
{
|
||||||
|
QString filePath = jarmodsPath().absoluteFilePath(jarmod->name);
|
||||||
|
mods.push_back(Mod(QFileInfo(filePath)));
|
||||||
|
}
|
||||||
|
return mods;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
QString OneSixInstance::intendedVersionId() const
|
QString OneSixInstance::intendedVersionId() const
|
||||||
{
|
{
|
||||||
return settings().get("IntendedVersion").toString();
|
return settings().get("IntendedVersion").toString();
|
||||||
@ -368,35 +327,16 @@ bool OneSixInstance::shouldUpdate() const
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OneSixInstance::versionIsCustom()
|
|
||||||
{
|
|
||||||
if (version)
|
|
||||||
{
|
|
||||||
return !version->isVanilla();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool OneSixInstance::versionIsFTBPack()
|
|
||||||
{
|
|
||||||
if (version)
|
|
||||||
{
|
|
||||||
return version->hasFtbPack();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString OneSixInstance::currentVersionId() const
|
QString OneSixInstance::currentVersionId() const
|
||||||
{
|
{
|
||||||
return intendedVersionId();
|
return intendedVersionId();
|
||||||
}
|
}
|
||||||
|
|
||||||
void OneSixInstance::reloadVersion()
|
void OneSixInstance::reloadProfile()
|
||||||
{
|
{
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
version->reload(externalPatches());
|
m_version->reload();
|
||||||
unsetFlag(VersionBrokenFlag);
|
unsetFlag(VersionBrokenFlag);
|
||||||
emit versionReloaded();
|
emit versionReloaded();
|
||||||
}
|
}
|
||||||
@ -405,7 +345,7 @@ void OneSixInstance::reloadVersion()
|
|||||||
}
|
}
|
||||||
catch (MMCError &error)
|
catch (MMCError &error)
|
||||||
{
|
{
|
||||||
version->clear();
|
m_version->clear();
|
||||||
setFlag(VersionBrokenFlag);
|
setFlag(VersionBrokenFlag);
|
||||||
// TODO: rethrow to show some error message(s)?
|
// TODO: rethrow to show some error message(s)?
|
||||||
emit versionReloaded();
|
emit versionReloaded();
|
||||||
@ -413,24 +353,20 @@ void OneSixInstance::reloadVersion()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OneSixInstance::clearVersion()
|
void OneSixInstance::clearProfile()
|
||||||
{
|
{
|
||||||
version->clear();
|
m_version->clear();
|
||||||
emit versionReloaded();
|
emit versionReloaded();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<InstanceVersion> OneSixInstance::getFullVersion() const
|
std::shared_ptr<MinecraftProfile> OneSixInstance::getMinecraftProfile() const
|
||||||
{
|
{
|
||||||
return version;
|
return m_version;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString OneSixInstance::getStatusbarDescription()
|
QString OneSixInstance::getStatusbarDescription()
|
||||||
{
|
{
|
||||||
QStringList traits;
|
QStringList traits;
|
||||||
if (versionIsCustom())
|
|
||||||
{
|
|
||||||
traits.append(tr("custom"));
|
|
||||||
}
|
|
||||||
if (flags() & VersionBrokenFlag)
|
if (flags() & VersionBrokenFlag)
|
||||||
{
|
{
|
||||||
traits.append(tr("broken"));
|
traits.append(tr("broken"));
|
||||||
@ -461,11 +397,6 @@ QDir OneSixInstance::versionsPath() const
|
|||||||
return QDir::current().absoluteFilePath("versions");
|
return QDir::current().absoluteFilePath("versions");
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList OneSixInstance::externalPatches() const
|
|
||||||
{
|
|
||||||
return QStringList();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool OneSixInstance::providesVersionFile() const
|
bool OneSixInstance::providesVersionFile() const
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@ -477,7 +408,7 @@ bool OneSixInstance::reload()
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
reloadVersion();
|
reloadProfile();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
@ -526,10 +457,11 @@ QString OneSixInstance::libDir() const
|
|||||||
QStringList OneSixInstance::extraArguments() const
|
QStringList OneSixInstance::extraArguments() const
|
||||||
{
|
{
|
||||||
auto list = BaseInstance::extraArguments();
|
auto list = BaseInstance::extraArguments();
|
||||||
auto version = getFullVersion();
|
auto version = getMinecraftProfile();
|
||||||
if (!version)
|
if (!version)
|
||||||
return list;
|
return list;
|
||||||
if (version->hasJarMods())
|
auto jarMods = getJarMods();
|
||||||
|
if (!jarMods.isEmpty())
|
||||||
{
|
{
|
||||||
list.append({"-Dfml.ignoreInvalidMinecraftCertificates=true",
|
list.append({"-Dfml.ignoreInvalidMinecraftCertificates=true",
|
||||||
"-Dfml.ignorePatchDiscrepancies=true"});
|
"-Dfml.ignorePatchDiscrepancies=true"});
|
||||||
|
@ -15,13 +15,13 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "BaseInstance.h"
|
#include "logic/minecraft/MinecraftInstance.h"
|
||||||
|
|
||||||
#include "logic/minecraft/InstanceVersion.h"
|
#include "logic/minecraft/MinecraftProfile.h"
|
||||||
#include "logic/ModList.h"
|
#include "logic/ModList.h"
|
||||||
#include "gui/pages/BasePageProvider.h"
|
#include "gui/pages/BasePageProvider.h"
|
||||||
|
|
||||||
class OneSixInstance : public BaseInstance, public BasePageProvider
|
class OneSixInstance : public MinecraftInstance, public BasePageProvider
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
@ -29,17 +29,19 @@ public:
|
|||||||
QObject *parent = 0);
|
QObject *parent = 0);
|
||||||
virtual ~OneSixInstance(){};
|
virtual ~OneSixInstance(){};
|
||||||
|
|
||||||
virtual void init() override;
|
virtual void init();
|
||||||
|
|
||||||
////// Edit Instance Dialog stuff //////
|
////// Edit Instance Dialog stuff //////
|
||||||
virtual QList<BasePage *> getPages();
|
virtual QList<BasePage *> getPages();
|
||||||
virtual QString dialogTitle();
|
virtual QString dialogTitle();
|
||||||
|
|
||||||
////// Mod Lists //////
|
////// Mod Lists //////
|
||||||
std::shared_ptr<ModList> loaderModList();
|
std::shared_ptr<ModList> loaderModList() const;
|
||||||
std::shared_ptr<ModList> coreModList();
|
std::shared_ptr<ModList> coreModList() const;
|
||||||
std::shared_ptr<ModList> resourcePackList() override;
|
std::shared_ptr<ModList> resourcePackList() const override;
|
||||||
std::shared_ptr<ModList> texturePackList() override;
|
std::shared_ptr<ModList> texturePackList() const override;
|
||||||
|
virtual QList<Mod> getJarMods() const override;
|
||||||
|
virtual void createProfile();
|
||||||
|
|
||||||
virtual QSet<QString> traits();
|
virtual QSet<QString> traits();
|
||||||
|
|
||||||
@ -53,7 +55,7 @@ public:
|
|||||||
virtual QString instanceConfigFolder() const override;
|
virtual QString instanceConfigFolder() const override;
|
||||||
|
|
||||||
virtual std::shared_ptr<Task> doUpdate() override;
|
virtual std::shared_ptr<Task> doUpdate() override;
|
||||||
virtual bool prepareForLaunch(AuthSessionPtr account, QString & launchScript) override;
|
virtual BaseProcess *prepareForLaunch(AuthSessionPtr account) override;
|
||||||
|
|
||||||
virtual void cleanupAfterRun() override;
|
virtual void cleanupAfterRun() override;
|
||||||
|
|
||||||
@ -66,30 +68,23 @@ public:
|
|||||||
virtual void setShouldUpdate(bool val) override;
|
virtual void setShouldUpdate(bool val) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* reload the full version json files.
|
* reload the profile, including version json files.
|
||||||
*
|
*
|
||||||
* throws various exceptions :3
|
* throws various exceptions :3
|
||||||
*/
|
*/
|
||||||
void reloadVersion();
|
void reloadProfile();
|
||||||
|
|
||||||
/// clears all version information in preparation for an update
|
/// clears all version information in preparation for an update
|
||||||
void clearVersion();
|
void clearProfile();
|
||||||
|
|
||||||
/// get the current full version info
|
/// get the current full version info
|
||||||
std::shared_ptr<InstanceVersion> getFullVersion() const;
|
std::shared_ptr<MinecraftProfile> getMinecraftProfile() const;
|
||||||
|
|
||||||
/// is the current version original, or custom?
|
|
||||||
virtual bool versionIsCustom() override;
|
|
||||||
|
|
||||||
/// does this instance have an FTB pack patch inside?
|
|
||||||
bool versionIsFTBPack();
|
|
||||||
|
|
||||||
virtual QString getStatusbarDescription() override;
|
virtual QString getStatusbarDescription() override;
|
||||||
|
|
||||||
virtual QDir jarmodsPath() const;
|
virtual QDir jarmodsPath() const;
|
||||||
virtual QDir librariesPath() const;
|
virtual QDir librariesPath() const;
|
||||||
virtual QDir versionsPath() const;
|
virtual QDir versionsPath() const;
|
||||||
virtual QStringList externalPatches() const;
|
|
||||||
virtual bool providesVersionFile() const;
|
virtual bool providesVersionFile() const;
|
||||||
|
|
||||||
bool reload() override;
|
bool reload() override;
|
||||||
@ -103,15 +98,13 @@ signals:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
QStringList processMinecraftArgs(AuthSessionPtr account);
|
QStringList processMinecraftArgs(AuthSessionPtr account);
|
||||||
QDir reconstructAssets(std::shared_ptr<InstanceVersion> version);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::shared_ptr<InstanceVersion> version;
|
std::shared_ptr<MinecraftProfile> m_version;
|
||||||
std::shared_ptr<ModList> jar_mod_list;
|
mutable std::shared_ptr<ModList> m_loader_mod_list;
|
||||||
std::shared_ptr<ModList> loader_mod_list;
|
mutable std::shared_ptr<ModList> m_core_mod_list;
|
||||||
std::shared_ptr<ModList> core_mod_list;
|
mutable std::shared_ptr<ModList> m_resource_pack_list;
|
||||||
std::shared_ptr<ModList> resource_pack_list;
|
mutable std::shared_ptr<ModList> m_texture_pack_list;
|
||||||
std::shared_ptr<ModList> texture_pack_list;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(std::shared_ptr<OneSixInstance>)
|
Q_DECLARE_METATYPE(std::shared_ptr<OneSixInstance>)
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
|
|
||||||
#include "logic/BaseInstance.h"
|
#include "logic/BaseInstance.h"
|
||||||
#include "logic/minecraft/MinecraftVersionList.h"
|
#include "logic/minecraft/MinecraftVersionList.h"
|
||||||
#include "logic/minecraft/InstanceVersion.h"
|
#include "logic/minecraft/MinecraftProfile.h"
|
||||||
#include "logic/minecraft/OneSixLibrary.h"
|
#include "logic/minecraft/OneSixLibrary.h"
|
||||||
#include "logic/OneSixInstance.h"
|
#include "logic/OneSixInstance.h"
|
||||||
#include "logic/forge/ForgeMirrors.h"
|
#include "logic/forge/ForgeMirrors.h"
|
||||||
@ -88,7 +88,7 @@ void OneSixUpdate::assetIndexStart()
|
|||||||
{
|
{
|
||||||
setStatus(tr("Updating assets index..."));
|
setStatus(tr("Updating assets index..."));
|
||||||
OneSixInstance *inst = (OneSixInstance *)m_inst;
|
OneSixInstance *inst = (OneSixInstance *)m_inst;
|
||||||
std::shared_ptr<InstanceVersion> version = inst->getFullVersion();
|
std::shared_ptr<MinecraftProfile> version = inst->getMinecraftProfile();
|
||||||
QString assetName = version->assets;
|
QString assetName = version->assets;
|
||||||
QUrl indexUrl = "http://" + URLConstants::AWS_DOWNLOAD_INDEXES + assetName + ".json";
|
QUrl indexUrl = "http://" + URLConstants::AWS_DOWNLOAD_INDEXES + assetName + ".json";
|
||||||
QString localPath = assetName + ".json";
|
QString localPath = assetName + ".json";
|
||||||
@ -112,7 +112,7 @@ void OneSixUpdate::assetIndexFinished()
|
|||||||
AssetsIndex index;
|
AssetsIndex index;
|
||||||
|
|
||||||
OneSixInstance *inst = (OneSixInstance *)m_inst;
|
OneSixInstance *inst = (OneSixInstance *)m_inst;
|
||||||
std::shared_ptr<InstanceVersion> version = inst->getFullVersion();
|
std::shared_ptr<MinecraftProfile> version = inst->getMinecraftProfile();
|
||||||
QString assetName = version->assets;
|
QString assetName = version->assets;
|
||||||
|
|
||||||
QString asset_fname = "assets/indexes/" + assetName + ".json";
|
QString asset_fname = "assets/indexes/" + assetName + ".json";
|
||||||
@ -177,7 +177,7 @@ void OneSixUpdate::jarlibStart()
|
|||||||
OneSixInstance *inst = (OneSixInstance *)m_inst;
|
OneSixInstance *inst = (OneSixInstance *)m_inst;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
inst->reloadVersion();
|
inst->reloadProfile();
|
||||||
}
|
}
|
||||||
catch (MMCError &e)
|
catch (MMCError &e)
|
||||||
{
|
{
|
||||||
@ -191,7 +191,7 @@ void OneSixUpdate::jarlibStart()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build a list of URLs that will need to be downloaded.
|
// Build a list of URLs that will need to be downloaded.
|
||||||
std::shared_ptr<InstanceVersion> version = inst->getFullVersion();
|
std::shared_ptr<MinecraftProfile> version = inst->getMinecraftProfile();
|
||||||
// minecraft.jar for this version
|
// minecraft.jar for this version
|
||||||
{
|
{
|
||||||
QString version_id = version->id;
|
QString version_id = version->id;
|
||||||
@ -290,7 +290,7 @@ void OneSixUpdate::jarlibStart()
|
|||||||
void OneSixUpdate::jarlibFinished()
|
void OneSixUpdate::jarlibFinished()
|
||||||
{
|
{
|
||||||
OneSixInstance *inst = (OneSixInstance *)m_inst;
|
OneSixInstance *inst = (OneSixInstance *)m_inst;
|
||||||
std::shared_ptr<InstanceVersion> version = inst->getFullVersion();
|
std::shared_ptr<MinecraftProfile> version = inst->getMinecraftProfile();
|
||||||
|
|
||||||
// nuke obsolete stripped jar(s) if needed
|
// nuke obsolete stripped jar(s) if needed
|
||||||
QString version_id = version->id;
|
QString version_id = version->id;
|
||||||
@ -311,22 +311,16 @@ void OneSixUpdate::jarlibFinished()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// create stripped jar, if needed
|
// create temporary modded jar, if needed
|
||||||
if (version->hasJarMods())
|
auto jarMods = inst->getJarMods();
|
||||||
|
if(jarMods.size())
|
||||||
{
|
{
|
||||||
auto sourceJarPath = m_inst->versionsPath().absoluteFilePath(version->id + "/" + version->id + ".jar");
|
auto sourceJarPath = m_inst->versionsPath().absoluteFilePath(version->id + "/" + version->id + ".jar");
|
||||||
QString localPath = version_id + "/" + version_id + ".jar";
|
QString localPath = version_id + "/" + version_id + ".jar";
|
||||||
auto metacache = MMC->metacache();
|
auto metacache = MMC->metacache();
|
||||||
auto entry = metacache->resolveEntry("versions", localPath);
|
auto entry = metacache->resolveEntry("versions", localPath);
|
||||||
QString fullJarPath = entry->getFullPath();
|
QString fullJarPath = entry->getFullPath();
|
||||||
//FIXME: remove need to convert to different objects here
|
if(!JarUtils::createModdedJar(sourceJarPath, finalJarPath, jarMods))
|
||||||
QList<Mod> mods;
|
|
||||||
for (auto jarmod : version->jarMods)
|
|
||||||
{
|
|
||||||
QString filePath = m_inst->jarmodsPath().absoluteFilePath(jarmod->name);
|
|
||||||
mods.push_back(Mod(QFileInfo(filePath)));
|
|
||||||
}
|
|
||||||
if(!JarUtils::createModdedJar(sourceJarPath, finalJarPath, mods))
|
|
||||||
{
|
{
|
||||||
emitFailed(tr("Failed to create the custom Minecraft jar file."));
|
emitFailed(tr("Failed to create the custom Minecraft jar file."));
|
||||||
return;
|
return;
|
||||||
@ -354,7 +348,7 @@ void OneSixUpdate::fmllibsStart()
|
|||||||
{
|
{
|
||||||
// Get the mod list
|
// Get the mod list
|
||||||
OneSixInstance *inst = (OneSixInstance *)m_inst;
|
OneSixInstance *inst = (OneSixInstance *)m_inst;
|
||||||
std::shared_ptr<InstanceVersion> fullversion = inst->getFullVersion();
|
std::shared_ptr<MinecraftProfile> fullversion = inst->getMinecraftProfile();
|
||||||
bool forge_present = false;
|
bool forge_present = false;
|
||||||
|
|
||||||
QString version = inst->intendedVersionId();
|
QString version = inst->intendedVersionId();
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
#include "logic/net/NetJob.h"
|
#include "logic/net/NetJob.h"
|
||||||
#include "logic/tasks/Task.h"
|
#include "logic/tasks/Task.h"
|
||||||
#include "logic/VersionFilterData.h"
|
#include "logic/minecraft/VersionFilterData.h"
|
||||||
#include <quazip.h>
|
#include <quazip.h>
|
||||||
|
|
||||||
class MinecraftVersion;
|
class MinecraftVersion;
|
||||||
|
@ -5,8 +5,6 @@
|
|||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
#include <QDirIterator>
|
#include <QDirIterator>
|
||||||
#include <QCryptographicHash>
|
#include <QCryptographicHash>
|
||||||
#include "gui/dialogs/CustomMessageBox.h"
|
|
||||||
#include <QDesktopServices>
|
|
||||||
|
|
||||||
AssetsMigrateTask::AssetsMigrateTask(int expected, QObject *parent)
|
AssetsMigrateTask::AssetsMigrateTask(int expected, QObject *parent)
|
||||||
: Task(parent)
|
: Task(parent)
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
#include "AssetsUtils.h"
|
#include "AssetsUtils.h"
|
||||||
#include "MultiMC.h"
|
#include "MultiMC.h"
|
||||||
|
#include <pathutils.h>
|
||||||
|
|
||||||
namespace AssetsUtils
|
namespace AssetsUtils
|
||||||
{
|
{
|
||||||
@ -151,4 +152,65 @@ bool loadAssetsIndexJson(QString path, AssetsIndex *index)
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QDir reconstructAssets(QString assetsId)
|
||||||
|
{
|
||||||
|
QDir assetsDir = QDir("assets/");
|
||||||
|
QDir indexDir = QDir(PathCombine(assetsDir.path(), "indexes"));
|
||||||
|
QDir objectDir = QDir(PathCombine(assetsDir.path(), "objects"));
|
||||||
|
QDir virtualDir = QDir(PathCombine(assetsDir.path(), "virtual"));
|
||||||
|
|
||||||
|
QString indexPath = PathCombine(indexDir.path(), assetsId + ".json");
|
||||||
|
QFile indexFile(indexPath);
|
||||||
|
QDir virtualRoot(PathCombine(virtualDir.path(), assetsId));
|
||||||
|
|
||||||
|
if (!indexFile.exists())
|
||||||
|
{
|
||||||
|
QLOG_ERROR() << "No assets index file" << indexPath << "; can't reconstruct assets";
|
||||||
|
return virtualRoot;
|
||||||
|
}
|
||||||
|
|
||||||
|
QLOG_DEBUG() << "reconstructAssets" << assetsDir.path() << indexDir.path()
|
||||||
|
<< objectDir.path() << virtualDir.path() << virtualRoot.path();
|
||||||
|
|
||||||
|
AssetsIndex index;
|
||||||
|
bool loadAssetsIndex = AssetsUtils::loadAssetsIndexJson(indexPath, &index);
|
||||||
|
|
||||||
|
if (loadAssetsIndex && index.isVirtual)
|
||||||
|
{
|
||||||
|
QLOG_INFO() << "Reconstructing virtual assets folder at" << virtualRoot.path();
|
||||||
|
|
||||||
|
for (QString map : index.objects.keys())
|
||||||
|
{
|
||||||
|
AssetObject asset_object = index.objects.value(map);
|
||||||
|
QString target_path = PathCombine(virtualRoot.path(), map);
|
||||||
|
QFile target(target_path);
|
||||||
|
|
||||||
|
QString tlk = asset_object.hash.left(2);
|
||||||
|
|
||||||
|
QString original_path =
|
||||||
|
PathCombine(PathCombine(objectDir.path(), tlk), asset_object.hash);
|
||||||
|
QFile original(original_path);
|
||||||
|
if (!original.exists())
|
||||||
|
continue;
|
||||||
|
if (!target.exists())
|
||||||
|
{
|
||||||
|
QFileInfo info(target_path);
|
||||||
|
QDir target_dir = info.dir();
|
||||||
|
// QLOG_DEBUG() << target_dir;
|
||||||
|
if (!target_dir.exists())
|
||||||
|
QDir("").mkpath(target_dir.path());
|
||||||
|
|
||||||
|
bool couldCopy = original.copy(target_path);
|
||||||
|
QLOG_DEBUG() << " Copying" << original_path << "to" << target_path
|
||||||
|
<< QString::number(couldCopy); // << original.errorString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Write last used time to virtualRoot/.lastused
|
||||||
|
}
|
||||||
|
|
||||||
|
return virtualRoot;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -34,4 +34,6 @@ namespace AssetsUtils
|
|||||||
{
|
{
|
||||||
bool loadAssetsIndexJson(QString file, AssetsIndex* index);
|
bool loadAssetsIndexJson(QString file, AssetsIndex* index);
|
||||||
int findLegacyAssets();
|
int findLegacyAssets();
|
||||||
|
/// Reconstruct a virtual assets folder for the given assets ID and return the folder
|
||||||
|
QDir reconstructAssets(QString assetsId);
|
||||||
}
|
}
|
||||||
|
@ -14,14 +14,13 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "ForgeInstaller.h"
|
#include "ForgeInstaller.h"
|
||||||
#include "logic/minecraft/InstanceVersion.h"
|
#include "logic/minecraft/MinecraftProfile.h"
|
||||||
#include "logic/minecraft/OneSixLibrary.h"
|
#include "logic/minecraft/OneSixLibrary.h"
|
||||||
#include "logic/net/HttpMetaCache.h"
|
#include "logic/net/HttpMetaCache.h"
|
||||||
#include "logic/tasks/Task.h"
|
#include "logic/tasks/Task.h"
|
||||||
#include "logic/OneSixInstance.h"
|
#include "logic/OneSixInstance.h"
|
||||||
#include "logic/forge/ForgeVersionList.h"
|
#include "logic/forge/ForgeVersionList.h"
|
||||||
#include "logic/VersionFilterData.h"
|
#include "logic/minecraft/VersionFilterData.h"
|
||||||
#include "gui/dialogs/ProgressDialog.h"
|
|
||||||
|
|
||||||
#include <quazip.h>
|
#include <quazip.h>
|
||||||
#include <quazipfile.h>
|
#include <quazipfile.h>
|
||||||
@ -41,7 +40,7 @@ ForgeInstaller::ForgeInstaller() : BaseInstaller()
|
|||||||
|
|
||||||
void ForgeInstaller::prepare(const QString &filename, const QString &universalUrl)
|
void ForgeInstaller::prepare(const QString &filename, const QString &universalUrl)
|
||||||
{
|
{
|
||||||
std::shared_ptr<InstanceVersion> newVersion;
|
std::shared_ptr<MinecraftProfile> newVersion;
|
||||||
m_universal_url = universalUrl;
|
m_universal_url = universalUrl;
|
||||||
|
|
||||||
QuaZip zip(filename);
|
QuaZip zip(filename);
|
||||||
@ -74,7 +73,7 @@ void ForgeInstaller::prepare(const QString &filename, const QString &universalUr
|
|||||||
|
|
||||||
// read the forge version info
|
// read the forge version info
|
||||||
{
|
{
|
||||||
newVersion = InstanceVersion::fromJson(versionInfoVal.toObject());
|
newVersion = MinecraftProfile::fromJson(versionInfoVal.toObject());
|
||||||
if (!newVersion)
|
if (!newVersion)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -116,7 +115,7 @@ void ForgeInstaller::prepare(const QString &filename, const QString &universalUr
|
|||||||
file.close();
|
file.close();
|
||||||
|
|
||||||
m_forge_json = newVersion;
|
m_forge_json = newVersion;
|
||||||
realVersionId = m_forge_json->id = installObj.value("minecraft").toString();
|
m_forge_json->id = installObj.value("minecraft").toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ForgeInstaller::add(OneSixInstance *to)
|
bool ForgeInstaller::add(OneSixInstance *to)
|
||||||
@ -194,7 +193,7 @@ bool ForgeInstaller::add(OneSixInstance *to)
|
|||||||
bool found = false;
|
bool found = false;
|
||||||
bool equals = false;
|
bool equals = false;
|
||||||
// find an entry that matches this one
|
// find an entry that matches this one
|
||||||
for (auto tolib : to->getFullVersion()->vanillaLibraries)
|
for (auto tolib : to->getMinecraftProfile()->vanillaLibraries)
|
||||||
{
|
{
|
||||||
if (tolib->artifactId() != libName)
|
if (tolib->artifactId() != libName)
|
||||||
continue;
|
continue;
|
||||||
@ -237,7 +236,7 @@ bool ForgeInstaller::add(OneSixInstance *to)
|
|||||||
match = expression.match(args);
|
match = expression.match(args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!args.isEmpty() && args != to->getFullVersion()->vanillaMinecraftArguments)
|
if (!args.isEmpty() && args != to->getMinecraftProfile()->vanillaMinecraftArguments)
|
||||||
{
|
{
|
||||||
obj.insert("minecraftArguments", args);
|
obj.insert("minecraftArguments", args);
|
||||||
}
|
}
|
||||||
@ -246,7 +245,7 @@ bool ForgeInstaller::add(OneSixInstance *to)
|
|||||||
obj.insert("+tweakers", QJsonArray::fromStringList(tweakers));
|
obj.insert("+tweakers", QJsonArray::fromStringList(tweakers));
|
||||||
}
|
}
|
||||||
if (!m_forge_json->processArguments.isEmpty() &&
|
if (!m_forge_json->processArguments.isEmpty() &&
|
||||||
m_forge_json->processArguments != to->getFullVersion()->vanillaProcessArguments)
|
m_forge_json->processArguments != to->getMinecraftProfile()->vanillaProcessArguments)
|
||||||
{
|
{
|
||||||
obj.insert("processArguments", m_forge_json->processArguments);
|
obj.insert("processArguments", m_forge_json->processArguments);
|
||||||
}
|
}
|
||||||
@ -308,7 +307,7 @@ bool ForgeInstaller::addLegacy(OneSixInstance *to)
|
|||||||
traitsPlus.append(QString("legacyFML"));
|
traitsPlus.append(QString("legacyFML"));
|
||||||
obj.insert("+traits", traitsPlus);
|
obj.insert("+traits", traitsPlus);
|
||||||
}
|
}
|
||||||
auto fullversion = to->getFullVersion();
|
auto fullversion = to->getMinecraftProfile();
|
||||||
fullversion->remove("net.minecraftforge");
|
fullversion->remove("net.minecraftforge");
|
||||||
|
|
||||||
QFile file(filename(to->instanceRoot()));
|
QFile file(filename(to->instanceRoot()));
|
||||||
@ -409,7 +408,7 @@ protected:
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
m_instance->reloadVersion();
|
m_instance->reloadProfile();
|
||||||
emitSucceeded();
|
emitSucceeded();
|
||||||
}
|
}
|
||||||
catch (MMCError &e)
|
catch (MMCError &e)
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
#include <QString>
|
#include <QString>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
class InstanceVersion;
|
class MinecraftProfile;
|
||||||
class ForgeInstallTask;
|
class ForgeInstallTask;
|
||||||
struct ForgeVersion;
|
struct ForgeVersion;
|
||||||
|
|
||||||
@ -40,12 +40,11 @@ protected:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
// the parsed version json, read from the installer
|
// the parsed version json, read from the installer
|
||||||
std::shared_ptr<InstanceVersion> m_forge_json;
|
std::shared_ptr<MinecraftProfile> m_forge_json;
|
||||||
// the actual forge version
|
// the actual forge version
|
||||||
std::shared_ptr<ForgeVersion> m_forge_version;
|
std::shared_ptr<ForgeVersion> m_forge_version;
|
||||||
QString internalPath;
|
QString internalPath;
|
||||||
QString finalPath;
|
QString finalPath;
|
||||||
QString realVersionId;
|
|
||||||
QString m_forgeVersionString;
|
QString m_forgeVersionString;
|
||||||
QString m_universal_url;
|
QString m_universal_url;
|
||||||
};
|
};
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#include "ForgeVersion.h"
|
#include "ForgeVersion.h"
|
||||||
#include "logic/VersionFilterData.h"
|
#include "logic/minecraft/VersionFilterData.h"
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
|
||||||
QString ForgeVersion::name()
|
QString ForgeVersion::name()
|
||||||
|
32
logic/ftb/FTBVersion.h
Normal file
32
logic/ftb/FTBVersion.h
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <logic/minecraft/MinecraftVersion.h>
|
||||||
|
|
||||||
|
class FTBVersion : public BaseVersion
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FTBVersion(MinecraftVersionPtr parent) : m_version(parent){};
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual QString descriptor() override
|
||||||
|
{
|
||||||
|
return m_version->descriptor();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual QString name() override
|
||||||
|
{
|
||||||
|
return m_version->name();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual QString typeString() const override
|
||||||
|
{
|
||||||
|
return m_version->typeString();
|
||||||
|
}
|
||||||
|
|
||||||
|
MinecraftVersionPtr getMinecraftVersion()
|
||||||
|
{
|
||||||
|
return m_version;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
MinecraftVersionPtr m_version;
|
||||||
|
};
|
@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "LegacyInstance.h"
|
#include "logic/LegacyInstance.h"
|
||||||
|
|
||||||
class LegacyFTBInstance : public LegacyInstance
|
class LegacyFTBInstance : public LegacyInstance
|
||||||
{
|
{
|
@ -1,11 +1,11 @@
|
|||||||
#include "OneSixFTBInstance.h"
|
#include "OneSixFTBInstance.h"
|
||||||
|
|
||||||
#include "logic/minecraft/InstanceVersion.h"
|
#include "logic/minecraft/MinecraftProfile.h"
|
||||||
#include "logic/minecraft/OneSixLibrary.h"
|
#include "logic/minecraft/OneSixLibrary.h"
|
||||||
#include "logic/minecraft/VersionBuilder.h"
|
#include "logic/minecraft/VersionBuilder.h"
|
||||||
#include "tasks/SequentialTask.h"
|
#include "logic/tasks/SequentialTask.h"
|
||||||
#include "forge/ForgeInstaller.h"
|
#include "logic/forge/ForgeInstaller.h"
|
||||||
#include "forge/ForgeVersionList.h"
|
#include "logic/forge/ForgeVersionList.h"
|
||||||
#include "MultiMC.h"
|
#include "MultiMC.h"
|
||||||
#include "pathutils.h"
|
#include "pathutils.h"
|
||||||
|
|
||||||
@ -109,11 +109,13 @@ QDir OneSixFTBInstance::versionsPath() const
|
|||||||
return QDir(MMC->settings()->get("FTBRoot").toString() + "/versions");
|
return QDir(MMC->settings()->get("FTBRoot").toString() + "/versions");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
QStringList OneSixFTBInstance::externalPatches() const
|
QStringList OneSixFTBInstance::externalPatches() const
|
||||||
{
|
{
|
||||||
return QStringList() << versionsPath().absoluteFilePath(intendedVersionId() + "/" + intendedVersionId() + ".json")
|
return QStringList() << versionsPath().absoluteFilePath(intendedVersionId() + "/" + intendedVersionId() + ".json")
|
||||||
<< minecraftRoot() + "/pack.json";
|
<< minecraftRoot() + "/pack.json";
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
bool OneSixFTBInstance::providesVersionFile() const
|
bool OneSixFTBInstance::providesVersionFile() const
|
||||||
{
|
{
|
@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "OneSixInstance.h"
|
#include "logic/OneSixInstance.h"
|
||||||
|
|
||||||
class OneSixLibrary;
|
class OneSixLibrary;
|
||||||
|
|
||||||
@ -22,7 +22,6 @@ public:
|
|||||||
|
|
||||||
QDir librariesPath() const override;
|
QDir librariesPath() const override;
|
||||||
QDir versionsPath() const override;
|
QDir versionsPath() const override;
|
||||||
QStringList externalPatches() const override;
|
|
||||||
bool providesVersionFile() const override;
|
bool providesVersionFile() const override;
|
||||||
|
|
||||||
private:
|
private:
|
@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
#include "logger/QsLog.h"
|
#include "logger/QsLog.h"
|
||||||
|
|
||||||
#include "logic/minecraft/InstanceVersion.h"
|
#include "logic/minecraft/MinecraftProfile.h"
|
||||||
#include "logic/minecraft/OneSixLibrary.h"
|
#include "logic/minecraft/OneSixLibrary.h"
|
||||||
#include "logic/OneSixInstance.h"
|
#include "logic/OneSixInstance.h"
|
||||||
#include "MultiMC.h"
|
#include "MultiMC.h"
|
||||||
@ -116,7 +116,7 @@ protected:
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
m_instance->reloadVersion();
|
m_instance->reloadProfile();
|
||||||
emitSucceeded();
|
emitSucceeded();
|
||||||
}
|
}
|
||||||
catch (MMCError &e)
|
catch (MMCError &e)
|
||||||
|
@ -11,30 +11,6 @@ JarmodPtr Jarmod::fromJson(const QJsonObject &libObj, const QString &filename)
|
|||||||
"contains a jarmod that doesn't have a 'name' field");
|
"contains a jarmod that doesn't have a 'name' field");
|
||||||
}
|
}
|
||||||
out->name = libObj.value("name").toString();
|
out->name = libObj.value("name").toString();
|
||||||
|
|
||||||
auto readString = [libObj, filename](const QString & key, QString & variable)
|
|
||||||
{
|
|
||||||
if (libObj.contains(key))
|
|
||||||
{
|
|
||||||
QJsonValue val = libObj.value(key);
|
|
||||||
if (!val.isString())
|
|
||||||
{
|
|
||||||
QLOG_WARN() << key << "is not a string in" << filename << "(skipping)";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
variable = val.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
readString("url", out->baseurl);
|
|
||||||
readString("MMC-hint", out->hint);
|
|
||||||
readString("MMC-absoluteUrl", out->absoluteUrl);
|
|
||||||
if(!out->baseurl.isEmpty() && out->absoluteUrl.isEmpty())
|
|
||||||
{
|
|
||||||
out->absoluteUrl = out->baseurl + out->name;
|
|
||||||
}
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,15 +18,5 @@ QJsonObject Jarmod::toJson()
|
|||||||
{
|
{
|
||||||
QJsonObject out;
|
QJsonObject out;
|
||||||
writeString(out, "name", name);
|
writeString(out, "name", name);
|
||||||
writeString(out, "url", baseurl);
|
|
||||||
writeString(out, "MMC-absoluteUrl", absoluteUrl);
|
|
||||||
writeString(out, "MMC-hint", hint);
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Jarmod::url()
|
|
||||||
{
|
|
||||||
if(!absoluteUrl.isEmpty())
|
|
||||||
return absoluteUrl;
|
|
||||||
else return baseurl + name;
|
|
||||||
}
|
|
||||||
|
@ -9,10 +9,6 @@ class Jarmod
|
|||||||
public: /* methods */
|
public: /* methods */
|
||||||
static JarmodPtr fromJson(const QJsonObject &libObj, const QString &filename);
|
static JarmodPtr fromJson(const QJsonObject &libObj, const QString &filename);
|
||||||
QJsonObject toJson();
|
QJsonObject toJson();
|
||||||
QString url();
|
|
||||||
public: /* data */
|
public: /* data */
|
||||||
QString name;
|
QString name;
|
||||||
QString baseurl;
|
|
||||||
QString hint;
|
|
||||||
QString absoluteUrl;
|
|
||||||
};
|
};
|
||||||
|
58
logic/minecraft/MinecraftInstance.cpp
Normal file
58
logic/minecraft/MinecraftInstance.cpp
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
#include "MinecraftInstance.h"
|
||||||
|
#include "MultiMC.h"
|
||||||
|
#include "logic/settings/SettingsObject.h"
|
||||||
|
#include <pathutils.h>
|
||||||
|
#include "logic/minecraft/MinecraftVersionList.h"
|
||||||
|
|
||||||
|
MinecraftInstance::MinecraftInstance(const QString &rootDir, SettingsObject *settings, QObject *parent)
|
||||||
|
: BaseInstance(rootDir, settings, parent)
|
||||||
|
{
|
||||||
|
auto globalSettings = MMC->settings();
|
||||||
|
|
||||||
|
// Java Settings
|
||||||
|
m_settings->registerSetting("OverrideJava", false);
|
||||||
|
m_settings->registerSetting("OverrideJavaLocation", false);
|
||||||
|
m_settings->registerSetting("OverrideJavaArgs", false);
|
||||||
|
m_settings->registerOverride(globalSettings->getSetting("JavaPath"));
|
||||||
|
m_settings->registerOverride(globalSettings->getSetting("JvmArgs"));
|
||||||
|
|
||||||
|
// Custom Commands
|
||||||
|
m_settings->registerSetting({"OverrideCommands","OverrideLaunchCmd"}, false);
|
||||||
|
m_settings->registerOverride(globalSettings->getSetting("PreLaunchCommand"));
|
||||||
|
m_settings->registerOverride(globalSettings->getSetting("PostExitCommand"));
|
||||||
|
|
||||||
|
// Window Size
|
||||||
|
m_settings->registerSetting("OverrideWindow", false);
|
||||||
|
m_settings->registerOverride(globalSettings->getSetting("LaunchMaximized"));
|
||||||
|
m_settings->registerOverride(globalSettings->getSetting("MinecraftWinWidth"));
|
||||||
|
m_settings->registerOverride(globalSettings->getSetting("MinecraftWinHeight"));
|
||||||
|
|
||||||
|
// Memory
|
||||||
|
m_settings->registerSetting("OverrideMemory", false);
|
||||||
|
m_settings->registerOverride(globalSettings->getSetting("MinMemAlloc"));
|
||||||
|
m_settings->registerOverride(globalSettings->getSetting("MaxMemAlloc"));
|
||||||
|
m_settings->registerOverride(globalSettings->getSetting("PermGen"));
|
||||||
|
|
||||||
|
// Console
|
||||||
|
m_settings->registerSetting("OverrideConsole", false);
|
||||||
|
m_settings->registerOverride(globalSettings->getSetting("ShowConsole"));
|
||||||
|
m_settings->registerOverride(globalSettings->getSetting("AutoCloseConsole"));
|
||||||
|
m_settings->registerOverride(globalSettings->getSetting("LogPrePostOutput"));
|
||||||
|
}
|
||||||
|
|
||||||
|
QString MinecraftInstance::minecraftRoot() const
|
||||||
|
{
|
||||||
|
QFileInfo mcDir(PathCombine(instanceRoot(), "minecraft"));
|
||||||
|
QFileInfo dotMCDir(PathCombine(instanceRoot(), ".minecraft"));
|
||||||
|
|
||||||
|
if (dotMCDir.exists() && !mcDir.exists())
|
||||||
|
return dotMCDir.filePath();
|
||||||
|
else
|
||||||
|
return mcDir.filePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr< BaseVersionList > MinecraftInstance::versionList() const
|
||||||
|
{
|
||||||
|
return std::dynamic_pointer_cast<BaseVersionList>(MMC->minecraftlist());
|
||||||
|
}
|
||||||
|
|
30
logic/minecraft/MinecraftInstance.h
Normal file
30
logic/minecraft/MinecraftInstance.h
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "logic/BaseInstance.h"
|
||||||
|
|
||||||
|
class MinecraftInstance: public BaseInstance
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MinecraftInstance(const QString& rootDir, SettingsObject* settings, QObject* parent = 0);
|
||||||
|
virtual ~MinecraftInstance() {};
|
||||||
|
|
||||||
|
/// Path to the instance's minecraft directory.
|
||||||
|
QString minecraftRoot() const;
|
||||||
|
|
||||||
|
////// Mod Lists //////
|
||||||
|
virtual std::shared_ptr<ModList> resourcePackList() const
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
virtual std::shared_ptr<ModList> texturePackList() const
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
/// get all jar mods applicable to this instance's jar
|
||||||
|
virtual QList<Mod> getJarMods() const
|
||||||
|
{
|
||||||
|
return QList<Mod>();
|
||||||
|
}
|
||||||
|
virtual std::shared_ptr< BaseVersionList > versionList() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::shared_ptr<MinecraftInstance> MinecraftInstancePtr;
|
216
logic/minecraft/MinecraftProcess.cpp
Normal file
216
logic/minecraft/MinecraftProcess.cpp
Normal file
@ -0,0 +1,216 @@
|
|||||||
|
/* Copyright 2013-2014 MultiMC Contributors
|
||||||
|
*
|
||||||
|
* Authors: Orochimarufan <orochimarufan.x3@gmail.com>
|
||||||
|
*
|
||||||
|
* 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 "MultiMC.h"
|
||||||
|
#include "BuildConfig.h"
|
||||||
|
|
||||||
|
#include "logic/minecraft/MinecraftProcess.h"
|
||||||
|
#include "logic/BaseInstance.h"
|
||||||
|
|
||||||
|
#include <QDataStream>
|
||||||
|
#include <QFile>
|
||||||
|
#include <QDir>
|
||||||
|
#include <QProcessEnvironment>
|
||||||
|
#include <QRegularExpression>
|
||||||
|
#include <QStandardPaths>
|
||||||
|
|
||||||
|
#include "osutils.h"
|
||||||
|
#include "pathutils.h"
|
||||||
|
#include "cmdutils.h"
|
||||||
|
|
||||||
|
#define IBUS "@im=ibus"
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
MinecraftProcess::MinecraftProcess(MinecraftInstancePtr inst) : BaseProcess(inst)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
MinecraftProcess* MinecraftProcess::create(MinecraftInstancePtr inst)
|
||||||
|
{
|
||||||
|
auto proc = new MinecraftProcess(inst);
|
||||||
|
proc->init();
|
||||||
|
return proc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QString MinecraftProcess::censorPrivateInfo(QString in)
|
||||||
|
{
|
||||||
|
if (!m_session)
|
||||||
|
return in;
|
||||||
|
|
||||||
|
if (m_session->session != "-")
|
||||||
|
in.replace(m_session->session, "<SESSION ID>");
|
||||||
|
in.replace(m_session->access_token, "<ACCESS TOKEN>");
|
||||||
|
in.replace(m_session->client_token, "<CLIENT TOKEN>");
|
||||||
|
in.replace(m_session->uuid, "<PROFILE ID>");
|
||||||
|
in.replace(m_session->player_name, "<PROFILE NAME>");
|
||||||
|
|
||||||
|
auto i = m_session->u.properties.begin();
|
||||||
|
while (i != m_session->u.properties.end())
|
||||||
|
{
|
||||||
|
in.replace(i.value(), "<" + i.key().toUpper() + ">");
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
// console window
|
||||||
|
MessageLevel::Enum MinecraftProcess::guessLevel(const QString &line, MessageLevel::Enum level)
|
||||||
|
{
|
||||||
|
QRegularExpression re("\\[(?<timestamp>[0-9:]+)\\] \\[[^/]+/(?<level>[^\\]]+)\\]");
|
||||||
|
auto match = re.match(line);
|
||||||
|
if(match.hasMatch())
|
||||||
|
{
|
||||||
|
// New style logs from log4j
|
||||||
|
QString timestamp = match.captured("timestamp");
|
||||||
|
QString levelStr = match.captured("level");
|
||||||
|
if(levelStr == "INFO")
|
||||||
|
level = MessageLevel::Message;
|
||||||
|
if(levelStr == "WARN")
|
||||||
|
level = MessageLevel::Warning;
|
||||||
|
if(levelStr == "ERROR")
|
||||||
|
level = MessageLevel::Error;
|
||||||
|
if(levelStr == "FATAL")
|
||||||
|
level = MessageLevel::Fatal;
|
||||||
|
if(levelStr == "TRACE" || levelStr == "DEBUG")
|
||||||
|
level = MessageLevel::Debug;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Old style forge logs
|
||||||
|
if (line.contains("[INFO]") || line.contains("[CONFIG]") || line.contains("[FINE]") ||
|
||||||
|
line.contains("[FINER]") || line.contains("[FINEST]"))
|
||||||
|
level = MessageLevel::Message;
|
||||||
|
if (line.contains("[SEVERE]") || line.contains("[STDERR]"))
|
||||||
|
level = MessageLevel::Error;
|
||||||
|
if (line.contains("[WARNING]"))
|
||||||
|
level = MessageLevel::Warning;
|
||||||
|
if (line.contains("[DEBUG]"))
|
||||||
|
level = MessageLevel::Debug;
|
||||||
|
}
|
||||||
|
if (line.contains("overwriting existing"))
|
||||||
|
return MessageLevel::Fatal;
|
||||||
|
if (line.contains("Exception in thread") || line.contains(QRegularExpression("\\s+at ")))
|
||||||
|
return MessageLevel::Error;
|
||||||
|
return level;
|
||||||
|
}
|
||||||
|
|
||||||
|
QMap<QString, QString> MinecraftProcess::getVariables() const
|
||||||
|
{
|
||||||
|
auto mcInstance = std::dynamic_pointer_cast<MinecraftInstance>(m_instance);
|
||||||
|
QMap<QString, QString> out;
|
||||||
|
out.insert("INST_NAME", mcInstance->name());
|
||||||
|
out.insert("INST_ID", mcInstance->id());
|
||||||
|
out.insert("INST_DIR", QDir(mcInstance->instanceRoot()).absolutePath());
|
||||||
|
out.insert("INST_MC_DIR", QDir(mcInstance->minecraftRoot()).absolutePath());
|
||||||
|
out.insert("INST_JAVA", mcInstance->settings().get("JavaPath").toString());
|
||||||
|
out.insert("INST_JAVA_ARGS", javaArguments().join(' '));
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList MinecraftProcess::javaArguments() const
|
||||||
|
{
|
||||||
|
QStringList args;
|
||||||
|
|
||||||
|
// custom args go first. we want to override them if we have our own here.
|
||||||
|
args.append(m_instance->extraArguments());
|
||||||
|
|
||||||
|
// OSX dock icon and name
|
||||||
|
#ifdef OSX
|
||||||
|
args << "-Xdock:icon=icon.png";
|
||||||
|
args << QString("-Xdock:name=\"%1\"").arg(m_instance->windowTitle());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// HACK: Stupid hack for Intel drivers. See: https://mojang.atlassian.net/browse/MCL-767
|
||||||
|
#ifdef Q_OS_WIN32
|
||||||
|
args << QString("-XX:HeapDumpPath=MojangTricksIntelDriversForPerformance_javaw.exe_"
|
||||||
|
"minecraft.exe.heapdump");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
args << QString("-Xms%1m").arg(m_instance->settings().get("MinMemAlloc").toInt());
|
||||||
|
args << QString("-Xmx%1m").arg(m_instance->settings().get("MaxMemAlloc").toInt());
|
||||||
|
auto permgen = m_instance->settings().get("PermGen").toInt();
|
||||||
|
if (permgen != 64)
|
||||||
|
{
|
||||||
|
args << QString("-XX:PermSize=%1m").arg(permgen);
|
||||||
|
}
|
||||||
|
args << "-Duser.language=en";
|
||||||
|
if (!m_nativeFolder.isEmpty())
|
||||||
|
args << QString("-Djava.library.path=%1").arg(m_nativeFolder);
|
||||||
|
args << "-jar" << PathCombine(MMC->bin(), "jars", "NewLaunch.jar");
|
||||||
|
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MinecraftProcess::arm()
|
||||||
|
{
|
||||||
|
emit log("MultiMC version: " + BuildConfig.printableVersionString() + "\n\n");
|
||||||
|
emit log("Minecraft folder is:\n" + workingDirectory() + "\n\n");
|
||||||
|
|
||||||
|
if (!preLaunch())
|
||||||
|
{
|
||||||
|
emit ended(m_instance, 1, QProcess::CrashExit);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_instance->setLastLaunch();
|
||||||
|
|
||||||
|
QStringList args = javaArguments();
|
||||||
|
|
||||||
|
QString JavaPath = m_instance->settings().get("JavaPath").toString();
|
||||||
|
emit log("Java path is:\n" + JavaPath + "\n\n");
|
||||||
|
QString allArgs = args.join(", ");
|
||||||
|
emit log("Java Arguments:\n[" + censorPrivateInfo(allArgs) + "]\n\n");
|
||||||
|
|
||||||
|
auto realJavaPath = QStandardPaths::findExecutable(JavaPath);
|
||||||
|
if (realJavaPath.isEmpty())
|
||||||
|
{
|
||||||
|
emit log(tr("The java binary \"%1\" couldn't be found. You may have to set up java "
|
||||||
|
"if Minecraft fails to launch.").arg(JavaPath),
|
||||||
|
MessageLevel::Warning);
|
||||||
|
}
|
||||||
|
|
||||||
|
// instantiate the launcher part
|
||||||
|
start(JavaPath, args);
|
||||||
|
if (!waitForStarted())
|
||||||
|
{
|
||||||
|
//: Error message displayed if instace can't start
|
||||||
|
emit log(tr("Could not launch minecraft!"), MessageLevel::Error);
|
||||||
|
m_instance->cleanupAfterRun();
|
||||||
|
emit launch_failed(m_instance);
|
||||||
|
// not running, failed
|
||||||
|
m_instance->setRunning(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// send the launch script to the launcher part
|
||||||
|
QByteArray bytes = launchScript.toUtf8();
|
||||||
|
writeData(bytes.constData(), bytes.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
void MinecraftProcess::launch()
|
||||||
|
{
|
||||||
|
QString launchString("launch\n");
|
||||||
|
QByteArray bytes = launchString.toUtf8();
|
||||||
|
writeData(bytes.constData(), bytes.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
void MinecraftProcess::abort()
|
||||||
|
{
|
||||||
|
QString launchString("abort\n");
|
||||||
|
QByteArray bytes = launchString.toUtf8();
|
||||||
|
writeData(bytes.constData(), bytes.length());
|
||||||
|
}
|
77
logic/minecraft/MinecraftProcess.h
Normal file
77
logic/minecraft/MinecraftProcess.h
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
/* Copyright 2013-2014 MultiMC Contributors
|
||||||
|
*
|
||||||
|
* Authors: Orochimarufan <orochimarufan.x3@gmail.com>
|
||||||
|
*
|
||||||
|
* 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 "logic/minecraft/MinecraftInstance.h"
|
||||||
|
#include "logic/BaseProcess.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The MinecraftProcess class
|
||||||
|
*/
|
||||||
|
class MinecraftProcess : public BaseProcess
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
protected:
|
||||||
|
MinecraftProcess(MinecraftInstancePtr inst);
|
||||||
|
public:
|
||||||
|
static MinecraftProcess *create(MinecraftInstancePtr inst);
|
||||||
|
|
||||||
|
virtual ~MinecraftProcess(){};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief start the launcher part with the provided launch script
|
||||||
|
*/
|
||||||
|
void arm() override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief launch the armed instance!
|
||||||
|
*/
|
||||||
|
void launch() override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief abort launch!
|
||||||
|
*/
|
||||||
|
void abort() override;
|
||||||
|
|
||||||
|
void setLaunchScript(QString script)
|
||||||
|
{
|
||||||
|
launchScript = script;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setNativeFolder(QString natives)
|
||||||
|
{
|
||||||
|
m_nativeFolder = natives;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void setLogin(AuthSessionPtr session)
|
||||||
|
{
|
||||||
|
m_session = session;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
AuthSessionPtr m_session;
|
||||||
|
QString launchScript;
|
||||||
|
QString m_nativeFolder;
|
||||||
|
|
||||||
|
virtual QMap<QString, QString> getVariables() const override;
|
||||||
|
|
||||||
|
QStringList javaArguments() const;
|
||||||
|
virtual QString censorPrivateInfo(QString in) override;
|
||||||
|
virtual MessageLevel::Enum guessLevel(const QString &message, MessageLevel::Enum defaultLevel) override;
|
||||||
|
};
|
@ -15,31 +15,50 @@
|
|||||||
|
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QUuid>
|
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
#include <QJsonArray>
|
#include <QJsonArray>
|
||||||
#include <pathutils.h>
|
#include <pathutils.h>
|
||||||
|
|
||||||
#include "logic/minecraft/InstanceVersion.h"
|
#include "logic/minecraft/MinecraftProfile.h"
|
||||||
#include "logic/minecraft/VersionBuilder.h"
|
#include "logic/minecraft/VersionBuilder.h"
|
||||||
|
#include "ProfileUtils.h"
|
||||||
|
#include "NullProfileStrategy.h"
|
||||||
#include "logic/OneSixInstance.h"
|
#include "logic/OneSixInstance.h"
|
||||||
|
|
||||||
InstanceVersion::InstanceVersion(OneSixInstance *instance, QObject *parent)
|
MinecraftProfile::MinecraftProfile(ProfileStrategy *strategy)
|
||||||
: QAbstractListModel(parent), m_instance(instance)
|
: QAbstractListModel()
|
||||||
{
|
{
|
||||||
|
setStrategy(strategy);
|
||||||
clear();
|
clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void InstanceVersion::reload(const QStringList &external)
|
void MinecraftProfile::setStrategy(ProfileStrategy* strategy)
|
||||||
|
{
|
||||||
|
Q_ASSERT(strategy != nullptr);
|
||||||
|
|
||||||
|
if(m_strategy != nullptr)
|
||||||
|
{
|
||||||
|
delete m_strategy;
|
||||||
|
m_strategy = nullptr;
|
||||||
|
}
|
||||||
|
m_strategy = strategy;
|
||||||
|
m_strategy->profile = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProfileStrategy* MinecraftProfile::strategy()
|
||||||
|
{
|
||||||
|
return m_strategy;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MinecraftProfile::reload()
|
||||||
{
|
{
|
||||||
m_externalPatches = external;
|
|
||||||
beginResetModel();
|
beginResetModel();
|
||||||
VersionBuilder::build(this, m_instance, m_externalPatches);
|
m_strategy->load();
|
||||||
reapply(true);
|
reapply();
|
||||||
endResetModel();
|
endResetModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
void InstanceVersion::clear()
|
void MinecraftProfile::clear()
|
||||||
{
|
{
|
||||||
id.clear();
|
id.clear();
|
||||||
m_updateTimeString.clear();
|
m_updateTimeString.clear();
|
||||||
@ -59,44 +78,45 @@ void InstanceVersion::clear()
|
|||||||
traits.clear();
|
traits.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InstanceVersion::canRemove(const int index) const
|
void MinecraftProfile::clearPatches()
|
||||||
|
{
|
||||||
|
beginResetModel();
|
||||||
|
VersionPatches.clear();
|
||||||
|
endResetModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MinecraftProfile::appendPatch(ProfilePatchPtr patch)
|
||||||
|
{
|
||||||
|
int index = VersionPatches.size();
|
||||||
|
beginInsertRows(QModelIndex(), index, index);
|
||||||
|
VersionPatches.append(patch);
|
||||||
|
endInsertRows();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MinecraftProfile::canRemove(const int index) const
|
||||||
{
|
{
|
||||||
return VersionPatches.at(index)->isMoveable();
|
return VersionPatches.at(index)->isMoveable();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InstanceVersion::preremove(VersionPatchPtr patch)
|
bool MinecraftProfile::remove(const int index)
|
||||||
{
|
|
||||||
bool ok = true;
|
|
||||||
for(auto & jarmod: patch->getJarMods())
|
|
||||||
{
|
|
||||||
QString fullpath =PathCombine(m_instance->jarModsDir(), jarmod->name);
|
|
||||||
QFileInfo finfo (fullpath);
|
|
||||||
if(finfo.exists())
|
|
||||||
ok &= QFile::remove(fullpath);
|
|
||||||
}
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool InstanceVersion::remove(const int index)
|
|
||||||
{
|
{
|
||||||
if (!canRemove(index))
|
if (!canRemove(index))
|
||||||
return false;
|
return false;
|
||||||
if(!preremove(VersionPatches[index]))
|
|
||||||
|
if(!m_strategy->removePatch(VersionPatches.at(index)))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
auto toDelete = VersionPatches.at(index)->getPatchFilename();
|
|
||||||
if(!QFile::remove(toDelete))
|
|
||||||
return false;
|
|
||||||
beginRemoveRows(QModelIndex(), index, index);
|
beginRemoveRows(QModelIndex(), index, index);
|
||||||
VersionPatches.removeAt(index);
|
VersionPatches.removeAt(index);
|
||||||
endRemoveRows();
|
endRemoveRows();
|
||||||
reapply(true);
|
reapply();
|
||||||
saveCurrentOrder();
|
saveCurrentOrder();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InstanceVersion::remove(const QString id)
|
bool MinecraftProfile::remove(const QString id)
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (auto patch : VersionPatches)
|
for (auto patch : VersionPatches)
|
||||||
@ -110,7 +130,7 @@ bool InstanceVersion::remove(const QString id)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString InstanceVersion::versionFileId(const int index) const
|
QString MinecraftProfile::versionFileId(const int index) const
|
||||||
{
|
{
|
||||||
if (index < 0 || index >= VersionPatches.size())
|
if (index < 0 || index >= VersionPatches.size())
|
||||||
{
|
{
|
||||||
@ -119,7 +139,7 @@ QString InstanceVersion::versionFileId(const int index) const
|
|||||||
return VersionPatches.at(index)->getPatchID();
|
return VersionPatches.at(index)->getPatchID();
|
||||||
}
|
}
|
||||||
|
|
||||||
VersionPatchPtr InstanceVersion::versionPatch(const QString &id)
|
ProfilePatchPtr MinecraftProfile::versionPatch(const QString &id)
|
||||||
{
|
{
|
||||||
for (auto file : VersionPatches)
|
for (auto file : VersionPatches)
|
||||||
{
|
{
|
||||||
@ -131,67 +151,27 @@ VersionPatchPtr InstanceVersion::versionPatch(const QString &id)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
VersionPatchPtr InstanceVersion::versionPatch(int index)
|
ProfilePatchPtr MinecraftProfile::versionPatch(int index)
|
||||||
{
|
{
|
||||||
if(index < 0 || index >= VersionPatches.size())
|
if(index < 0 || index >= VersionPatches.size())
|
||||||
return 0;
|
return 0;
|
||||||
return VersionPatches[index];
|
return VersionPatches[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MinecraftProfile::isVanilla()
|
||||||
bool InstanceVersion::hasJarMods()
|
|
||||||
{
|
{
|
||||||
return !jarMods.isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool InstanceVersion::hasFtbPack()
|
|
||||||
{
|
|
||||||
return versionPatch("org.multimc.ftb.pack.json") != nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool InstanceVersion::removeFtbPack()
|
|
||||||
{
|
|
||||||
return remove("org.multimc.ftb.pack.json");
|
|
||||||
}
|
|
||||||
|
|
||||||
bool InstanceVersion::isVanilla()
|
|
||||||
{
|
|
||||||
QDir patches(PathCombine(m_instance->instanceRoot(), "patches/"));
|
|
||||||
for(auto patchptr: VersionPatches)
|
for(auto patchptr: VersionPatches)
|
||||||
{
|
{
|
||||||
if(patchptr->isCustom())
|
if(patchptr->isCustom())
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if(QFile::exists(PathCombine(m_instance->instanceRoot(), "custom.json")))
|
|
||||||
return false;
|
|
||||||
if(QFile::exists(PathCombine(m_instance->instanceRoot(), "version.json")))
|
|
||||||
return false;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InstanceVersion::revertToVanilla()
|
bool MinecraftProfile::revertToVanilla()
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
beginResetModel();
|
beginResetModel();
|
||||||
// remove custom.json, if present
|
|
||||||
QString customPath = PathCombine(m_instance->instanceRoot(), "custom.json");
|
|
||||||
if(QFile::exists(customPath))
|
|
||||||
{
|
|
||||||
if(!QFile::remove(customPath))
|
|
||||||
{
|
|
||||||
endResetModel();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// remove version.json, if present
|
|
||||||
QString versionPath = PathCombine(m_instance->instanceRoot(), "version.json");
|
|
||||||
if(QFile::exists(versionPath))
|
|
||||||
{
|
|
||||||
if(!QFile::remove(versionPath))
|
|
||||||
{
|
|
||||||
endResetModel();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// remove patches, if present
|
// remove patches, if present
|
||||||
auto it = VersionPatches.begin();
|
auto it = VersionPatches.begin();
|
||||||
while (it != VersionPatches.end())
|
while (it != VersionPatches.end())
|
||||||
@ -215,49 +195,15 @@ bool InstanceVersion::revertToVanilla()
|
|||||||
else
|
else
|
||||||
it++;
|
it++;
|
||||||
}
|
}
|
||||||
reapply(true);
|
reapply();
|
||||||
endResetModel();
|
endResetModel();
|
||||||
saveCurrentOrder();
|
saveCurrentOrder();
|
||||||
return true;
|
return true;
|
||||||
}
|
*/
|
||||||
|
|
||||||
bool InstanceVersion::hasDeprecatedVersionFiles()
|
|
||||||
{
|
|
||||||
if(QFile::exists(PathCombine(m_instance->instanceRoot(), "custom.json")))
|
|
||||||
return true;
|
|
||||||
if(QFile::exists(PathCombine(m_instance->instanceRoot(), "version.json")))
|
|
||||||
return true;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InstanceVersion::removeDeprecatedVersionFiles()
|
QList<std::shared_ptr<OneSixLibrary> > MinecraftProfile::getActiveNormalLibs()
|
||||||
{
|
|
||||||
beginResetModel();
|
|
||||||
// remove custom.json, if present
|
|
||||||
QString customPath = PathCombine(m_instance->instanceRoot(), "custom.json");
|
|
||||||
if(QFile::exists(customPath))
|
|
||||||
{
|
|
||||||
if(!QFile::remove(customPath))
|
|
||||||
{
|
|
||||||
endResetModel();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// remove version.json, if present
|
|
||||||
QString versionPath = PathCombine(m_instance->instanceRoot(), "version.json");
|
|
||||||
if(QFile::exists(versionPath))
|
|
||||||
{
|
|
||||||
if(!QFile::remove(versionPath))
|
|
||||||
{
|
|
||||||
endResetModel();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
endResetModel();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
QList<std::shared_ptr<OneSixLibrary> > InstanceVersion::getActiveNormalLibs()
|
|
||||||
{
|
{
|
||||||
QList<std::shared_ptr<OneSixLibrary> > output;
|
QList<std::shared_ptr<OneSixLibrary> > output;
|
||||||
for (auto lib : libraries)
|
for (auto lib : libraries)
|
||||||
@ -277,7 +223,8 @@ QList<std::shared_ptr<OneSixLibrary> > InstanceVersion::getActiveNormalLibs()
|
|||||||
}
|
}
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
QList<std::shared_ptr<OneSixLibrary> > InstanceVersion::getActiveNativeLibs()
|
|
||||||
|
QList<std::shared_ptr<OneSixLibrary> > MinecraftProfile::getActiveNativeLibs()
|
||||||
{
|
{
|
||||||
QList<std::shared_ptr<OneSixLibrary> > output;
|
QList<std::shared_ptr<OneSixLibrary> > output;
|
||||||
for (auto lib : libraries)
|
for (auto lib : libraries)
|
||||||
@ -290,9 +237,9 @@ QList<std::shared_ptr<OneSixLibrary> > InstanceVersion::getActiveNativeLibs()
|
|||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<InstanceVersion> InstanceVersion::fromJson(const QJsonObject &obj)
|
std::shared_ptr<MinecraftProfile> MinecraftProfile::fromJson(const QJsonObject &obj)
|
||||||
{
|
{
|
||||||
std::shared_ptr<InstanceVersion> version(new InstanceVersion(0));
|
std::shared_ptr<MinecraftProfile> version(new MinecraftProfile(new NullProfileStrategy()));
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
VersionBuilder::readJsonAndApplyToVersion(version.get(), obj);
|
VersionBuilder::readJsonAndApplyToVersion(version.get(), obj);
|
||||||
@ -304,7 +251,7 @@ std::shared_ptr<InstanceVersion> InstanceVersion::fromJson(const QJsonObject &ob
|
|||||||
return version;
|
return version;
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant InstanceVersion::data(const QModelIndex &index, int role) const
|
QVariant MinecraftProfile::data(const QModelIndex &index, int role) const
|
||||||
{
|
{
|
||||||
if (!index.isValid())
|
if (!index.isValid())
|
||||||
return QVariant();
|
return QVariant();
|
||||||
@ -329,7 +276,7 @@ QVariant InstanceVersion::data(const QModelIndex &index, int role) const
|
|||||||
}
|
}
|
||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
QVariant InstanceVersion::headerData(int section, Qt::Orientation orientation, int role) const
|
QVariant MinecraftProfile::headerData(int section, Qt::Orientation orientation, int role) const
|
||||||
{
|
{
|
||||||
if (orientation == Qt::Horizontal)
|
if (orientation == Qt::Horizontal)
|
||||||
{
|
{
|
||||||
@ -348,36 +295,36 @@ QVariant InstanceVersion::headerData(int section, Qt::Orientation orientation, i
|
|||||||
}
|
}
|
||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
Qt::ItemFlags InstanceVersion::flags(const QModelIndex &index) const
|
Qt::ItemFlags MinecraftProfile::flags(const QModelIndex &index) const
|
||||||
{
|
{
|
||||||
if (!index.isValid())
|
if (!index.isValid())
|
||||||
return Qt::NoItemFlags;
|
return Qt::NoItemFlags;
|
||||||
return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
|
return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
int InstanceVersion::rowCount(const QModelIndex &parent) const
|
int MinecraftProfile::rowCount(const QModelIndex &parent) const
|
||||||
{
|
{
|
||||||
return VersionPatches.size();
|
return VersionPatches.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
int InstanceVersion::columnCount(const QModelIndex &parent) const
|
int MinecraftProfile::columnCount(const QModelIndex &parent) const
|
||||||
{
|
{
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InstanceVersion::saveCurrentOrder() const
|
void MinecraftProfile::saveCurrentOrder() const
|
||||||
{
|
{
|
||||||
PatchOrder order;
|
ProfileUtils::PatchOrder order;
|
||||||
for(auto item: VersionPatches)
|
for(auto item: VersionPatches)
|
||||||
{
|
{
|
||||||
if(!item->isMoveable())
|
if(!item->isMoveable())
|
||||||
continue;
|
continue;
|
||||||
order.append(item->getPatchID());
|
order.append(item->getPatchID());
|
||||||
}
|
}
|
||||||
VersionBuilder::writeOverrideOrders(m_instance, order);
|
m_strategy->saveOrder(order);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InstanceVersion::move(const int index, const MoveDirection direction)
|
void MinecraftProfile::move(const int index, const MoveDirection direction)
|
||||||
{
|
{
|
||||||
int theirIndex;
|
int theirIndex;
|
||||||
if (direction == MoveUp)
|
if (direction == MoveUp)
|
||||||
@ -412,13 +359,13 @@ void InstanceVersion::move(const int index, const MoveDirection direction)
|
|||||||
saveCurrentOrder();
|
saveCurrentOrder();
|
||||||
reapply();
|
reapply();
|
||||||
}
|
}
|
||||||
void InstanceVersion::resetOrder()
|
void MinecraftProfile::resetOrder()
|
||||||
{
|
{
|
||||||
QDir(m_instance->instanceRoot()).remove("order.json");
|
m_strategy->resetOrder();
|
||||||
reload(m_externalPatches);
|
reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
void InstanceVersion::reapply(const bool alreadyReseting)
|
void MinecraftProfile::reapply()
|
||||||
{
|
{
|
||||||
clear();
|
clear();
|
||||||
for(auto file: VersionPatches)
|
for(auto file: VersionPatches)
|
||||||
@ -428,7 +375,7 @@ void InstanceVersion::reapply(const bool alreadyReseting)
|
|||||||
finalize();
|
finalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void InstanceVersion::finalize()
|
void MinecraftProfile::finalize()
|
||||||
{
|
{
|
||||||
// HACK: deny april fools. my head hurts enough already.
|
// HACK: deny april fools. my head hurts enough already.
|
||||||
QDate now = QDate::currentDate();
|
QDate now = QDate::currentDate();
|
||||||
@ -465,78 +412,15 @@ void InstanceVersion::finalize()
|
|||||||
finalizeArguments(minecraftArguments, processArguments);
|
finalizeArguments(minecraftArguments, processArguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InstanceVersion::installJarMods(QStringList selectedFiles)
|
void MinecraftProfile::installJarMods(QStringList selectedFiles)
|
||||||
{
|
{
|
||||||
for(auto filename: selectedFiles)
|
m_strategy->installJarMods(selectedFiles);
|
||||||
{
|
|
||||||
installJarModByFilename(filename);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void InstanceVersion::installJarModByFilename(QString filepath)
|
/*
|
||||||
{
|
* TODO: get rid of this. Get rid of all order numbers.
|
||||||
QString patchDir = PathCombine(m_instance->instanceRoot(), "patches");
|
*/
|
||||||
if(!ensureFolderPathExists(patchDir))
|
int MinecraftProfile::getFreeOrderNumber()
|
||||||
{
|
|
||||||
// THROW...
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ensureFolderPathExists(m_instance->jarModsDir()))
|
|
||||||
{
|
|
||||||
// THROW...
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QFileInfo sourceInfo(filepath);
|
|
||||||
auto uuid = QUuid::createUuid();
|
|
||||||
QString id = uuid.toString().remove('{').remove('}');
|
|
||||||
QString target_filename = id + ".jar";
|
|
||||||
QString target_id = "org.multimc.jarmod." + id;
|
|
||||||
QString target_name = sourceInfo.completeBaseName() + " (jar mod)";
|
|
||||||
QString finalPath = PathCombine(m_instance->jarModsDir(), target_filename);
|
|
||||||
|
|
||||||
QFileInfo targetInfo(finalPath);
|
|
||||||
if(targetInfo.exists())
|
|
||||||
{
|
|
||||||
// THROW
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!QFile::copy(sourceInfo.absoluteFilePath(),QFileInfo(finalPath).absoluteFilePath()))
|
|
||||||
{
|
|
||||||
// THROW
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto f = std::make_shared<VersionFile>();
|
|
||||||
auto jarMod = std::make_shared<Jarmod>();
|
|
||||||
jarMod->name = target_filename;
|
|
||||||
f->jarMods.append(jarMod);
|
|
||||||
f->name = target_name;
|
|
||||||
f->fileId = target_id;
|
|
||||||
f->order = getFreeOrderNumber();
|
|
||||||
QString patchFileName = PathCombine(patchDir, target_id + ".json");
|
|
||||||
f->filename = patchFileName;
|
|
||||||
|
|
||||||
QFile file(patchFileName);
|
|
||||||
if (!file.open(QFile::WriteOnly))
|
|
||||||
{
|
|
||||||
QLOG_ERROR() << "Error opening" << file.fileName()
|
|
||||||
<< "for reading:" << file.errorString();
|
|
||||||
return;
|
|
||||||
// THROW
|
|
||||||
}
|
|
||||||
file.write(f->toJson(true).toJson());
|
|
||||||
file.close();
|
|
||||||
int index = VersionPatches.size();
|
|
||||||
beginInsertRows(QModelIndex(), index, index);
|
|
||||||
VersionPatches.append(f);
|
|
||||||
endInsertRows();
|
|
||||||
saveCurrentOrder();
|
|
||||||
}
|
|
||||||
|
|
||||||
int InstanceVersion::getFreeOrderNumber()
|
|
||||||
{
|
{
|
||||||
int largest = 100;
|
int largest = 100;
|
||||||
// yes, I do realize this is dumb. The order thing itself is dumb. and to be removed next.
|
// yes, I do realize this is dumb. The order thing itself is dumb. and to be removed next.
|
@ -25,13 +25,22 @@
|
|||||||
#include "VersionFile.h"
|
#include "VersionFile.h"
|
||||||
#include "JarMod.h"
|
#include "JarMod.h"
|
||||||
|
|
||||||
|
class ProfileStrategy;
|
||||||
class OneSixInstance;
|
class OneSixInstance;
|
||||||
|
|
||||||
class InstanceVersion : public QAbstractListModel
|
class MinecraftProfile : public QAbstractListModel
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
friend class ProfileStrategy;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit InstanceVersion(OneSixInstance *instance, QObject *parent = 0);
|
explicit MinecraftProfile(ProfileStrategy *strategy);
|
||||||
|
|
||||||
|
/// construct a MinecraftProfile from a single file
|
||||||
|
static std::shared_ptr<MinecraftProfile> fromJson(const QJsonObject &obj);
|
||||||
|
|
||||||
|
void setStrategy(ProfileStrategy * strategy);
|
||||||
|
ProfileStrategy *strategy();
|
||||||
|
|
||||||
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
|
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
|
||||||
virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const;
|
virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const;
|
||||||
@ -39,57 +48,72 @@ public:
|
|||||||
virtual int columnCount(const QModelIndex &parent) const;
|
virtual int columnCount(const QModelIndex &parent) const;
|
||||||
virtual Qt::ItemFlags flags(const QModelIndex &index) const;
|
virtual Qt::ItemFlags flags(const QModelIndex &index) const;
|
||||||
|
|
||||||
void reload(const QStringList &external = QStringList());
|
/// is this version unchanged by the user?
|
||||||
void clear();
|
|
||||||
|
|
||||||
bool canRemove(const int index) const;
|
|
||||||
|
|
||||||
QString versionFileId(const int index) const;
|
|
||||||
|
|
||||||
// is this version unmodded vanilla minecraft?
|
|
||||||
bool isVanilla();
|
bool isVanilla();
|
||||||
// remove any customizations on top of vanilla
|
|
||||||
|
/// remove any customizations on top of whatever 'vanilla' means
|
||||||
bool revertToVanilla();
|
bool revertToVanilla();
|
||||||
|
|
||||||
// does this version consist of obsolete files?
|
/// install more jar mods
|
||||||
bool hasDeprecatedVersionFiles();
|
|
||||||
// remove obsolete files
|
|
||||||
bool removeDeprecatedVersionFiles();
|
|
||||||
|
|
||||||
// does this version have an FTB pack patch file?
|
|
||||||
bool hasFtbPack();
|
|
||||||
// remove FTB pack
|
|
||||||
bool removeFtbPack();
|
|
||||||
|
|
||||||
// does this version have any jar mods?
|
|
||||||
bool hasJarMods();
|
|
||||||
void installJarMods(QStringList selectedFiles);
|
void installJarMods(QStringList selectedFiles);
|
||||||
void installJarModByFilename(QString filepath);
|
|
||||||
|
/// DEPRECATED, remove ASAP
|
||||||
|
int getFreeOrderNumber();
|
||||||
|
|
||||||
|
/// Can patch file # be removed?
|
||||||
|
bool canRemove(const int index) const;
|
||||||
|
|
||||||
enum MoveDirection { MoveUp, MoveDown };
|
enum MoveDirection { MoveUp, MoveDown };
|
||||||
|
/// move patch file # up or down the list
|
||||||
void move(const int index, const MoveDirection direction);
|
void move(const int index, const MoveDirection direction);
|
||||||
void resetOrder();
|
|
||||||
|
|
||||||
// clears and reapplies all version files
|
/// remove patch file # - including files/records
|
||||||
void reapply(const bool alreadyReseting = false);
|
|
||||||
void finalize();
|
|
||||||
|
|
||||||
public
|
|
||||||
slots:
|
|
||||||
bool remove(const int index);
|
bool remove(const int index);
|
||||||
|
|
||||||
|
/// remove patch file by id - including files/records
|
||||||
bool remove(const QString id);
|
bool remove(const QString id);
|
||||||
|
|
||||||
|
void resetOrder();
|
||||||
|
|
||||||
|
/// reload all profile patches from storage, clear the profile and apply the patches
|
||||||
|
void reload();
|
||||||
|
|
||||||
|
/// clear the profile
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
/// apply the patches
|
||||||
|
void reapply();
|
||||||
|
|
||||||
|
/// do a finalization step (should always be done after applying all patches to profile)
|
||||||
|
void finalize();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
/// get all java libraries that belong to the classpath
|
||||||
QList<std::shared_ptr<OneSixLibrary>> getActiveNormalLibs();
|
QList<std::shared_ptr<OneSixLibrary>> getActiveNormalLibs();
|
||||||
|
|
||||||
|
/// get all native libraries that need to be available to the process
|
||||||
QList<std::shared_ptr<OneSixLibrary>> getActiveNativeLibs();
|
QList<std::shared_ptr<OneSixLibrary>> getActiveNativeLibs();
|
||||||
|
|
||||||
static std::shared_ptr<InstanceVersion> fromJson(const QJsonObject &obj);
|
/// get file ID of the patch file at #
|
||||||
|
QString versionFileId(const int index) const;
|
||||||
|
|
||||||
private:
|
/// get the profile patch by id
|
||||||
bool preremove(VersionPatchPtr patch);
|
ProfilePatchPtr versionPatch(const QString &id);
|
||||||
|
|
||||||
// data members
|
/// get the profile patch by index
|
||||||
public:
|
ProfilePatchPtr versionPatch(int index);
|
||||||
|
|
||||||
|
/// save the current patch order
|
||||||
|
void saveCurrentOrder() const;
|
||||||
|
|
||||||
|
public: /* only use in ProfileStrategy */
|
||||||
|
/// Remove all the patches
|
||||||
|
void clearPatches();
|
||||||
|
|
||||||
|
/// Add the patch object to the internal list of patches
|
||||||
|
void appendPatch(ProfilePatchPtr patch);
|
||||||
|
|
||||||
|
public: /* data */
|
||||||
/// the ID - determines which jar to use! ACTUALLY IMPORTANT!
|
/// the ID - determines which jar to use! ACTUALLY IMPORTANT!
|
||||||
QString id;
|
QString id;
|
||||||
|
|
||||||
@ -171,14 +195,7 @@ public:
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
// QList<Rule> rules;
|
// QList<Rule> rules;
|
||||||
|
|
||||||
QList<VersionPatchPtr> VersionPatches;
|
|
||||||
VersionPatchPtr versionPatch(const QString &id);
|
|
||||||
VersionPatchPtr versionPatch(int index);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QStringList m_externalPatches;
|
QList<ProfilePatchPtr> VersionPatches;
|
||||||
OneSixInstance *m_instance;
|
ProfileStrategy *m_strategy = nullptr;
|
||||||
void saveCurrentOrder() const;
|
|
||||||
int getFreeOrderNumber();
|
|
||||||
};
|
};
|
@ -1,7 +1,8 @@
|
|||||||
#include "MinecraftVersion.h"
|
#include "MinecraftVersion.h"
|
||||||
#include "InstanceVersion.h"
|
#include "MinecraftProfile.h"
|
||||||
#include "VersionBuildError.h"
|
#include "VersionBuildError.h"
|
||||||
#include "VersionBuilder.h"
|
#include "VersionBuilder.h"
|
||||||
|
#include "ProfileUtils.h"
|
||||||
#include "MultiMC.h"
|
#include "MultiMC.h"
|
||||||
#include "logic/settings/SettingsObject.h"
|
#include "logic/settings/SettingsObject.h"
|
||||||
|
|
||||||
@ -56,15 +57,20 @@ bool MinecraftVersion::isMinecraftVersion()
|
|||||||
|
|
||||||
// 1. assume the local file is good. load, check. If it's good, apply.
|
// 1. assume the local file is good. load, check. If it's good, apply.
|
||||||
// 2. if discrepancies are found, fall out and fail (impossible to apply incomplete version).
|
// 2. if discrepancies are found, fall out and fail (impossible to apply incomplete version).
|
||||||
void MinecraftVersion::applyFileTo(InstanceVersion *version)
|
void MinecraftVersion::applyFileTo(MinecraftProfile *version)
|
||||||
|
{
|
||||||
|
getVersionFile()->applyTo(version);
|
||||||
|
}
|
||||||
|
|
||||||
|
VersionFilePtr MinecraftVersion::getVersionFile()
|
||||||
{
|
{
|
||||||
QFileInfo versionFile(QString("versions/%1/%1.dat").arg(m_descriptor));
|
QFileInfo versionFile(QString("versions/%1/%1.dat").arg(m_descriptor));
|
||||||
|
|
||||||
auto versionObj = VersionBuilder::parseBinaryJsonFile(versionFile);
|
return ProfileUtils::parseBinaryJsonFile(versionFile);
|
||||||
versionObj->applyTo(version);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MinecraftVersion::applyTo(InstanceVersion *version)
|
|
||||||
|
void MinecraftVersion::applyTo(MinecraftProfile *version)
|
||||||
{
|
{
|
||||||
// do we have this one cached?
|
// do we have this one cached?
|
||||||
if (m_versionSource == Local)
|
if (m_versionSource == Local)
|
||||||
|
@ -20,15 +20,15 @@
|
|||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
|
|
||||||
#include "logic/BaseVersion.h"
|
#include "logic/BaseVersion.h"
|
||||||
#include "VersionPatch.h"
|
#include "ProfilePatch.h"
|
||||||
#include "VersionFile.h"
|
#include "VersionFile.h"
|
||||||
#include "VersionSource.h"
|
#include "VersionSource.h"
|
||||||
|
|
||||||
class InstanceVersion;
|
class MinecraftProfile;
|
||||||
class MinecraftVersion;
|
class MinecraftVersion;
|
||||||
typedef std::shared_ptr<MinecraftVersion> MinecraftVersionPtr;
|
typedef std::shared_ptr<MinecraftVersion> MinecraftVersionPtr;
|
||||||
|
|
||||||
class MinecraftVersion : public BaseVersion, public VersionPatch
|
class MinecraftVersion : public BaseVersion, public ProfilePatch
|
||||||
{
|
{
|
||||||
public: /* methods */
|
public: /* methods */
|
||||||
bool usesLegacyLauncher();
|
bool usesLegacyLauncher();
|
||||||
@ -37,9 +37,9 @@ public: /* methods */
|
|||||||
virtual QString typeString() const override;
|
virtual QString typeString() const override;
|
||||||
virtual bool hasJarMods() override;
|
virtual bool hasJarMods() override;
|
||||||
virtual bool isMinecraftVersion() override;
|
virtual bool isMinecraftVersion() override;
|
||||||
virtual void applyTo(InstanceVersion *version) override;
|
virtual void applyTo(MinecraftProfile *version) override;
|
||||||
virtual int getOrder();
|
virtual int getOrder() override;
|
||||||
virtual void setOrder(int order);
|
virtual void setOrder(int order) override;
|
||||||
virtual QList<JarmodPtr> getJarMods() override;
|
virtual QList<JarmodPtr> getJarMods() override;
|
||||||
virtual QString getPatchID() override;
|
virtual QString getPatchID() override;
|
||||||
virtual QString getPatchVersion() override;
|
virtual QString getPatchVersion() override;
|
||||||
@ -47,10 +47,12 @@ public: /* methods */
|
|||||||
virtual QString getPatchFilename() override;
|
virtual QString getPatchFilename() override;
|
||||||
bool needsUpdate();
|
bool needsUpdate();
|
||||||
bool hasUpdate();
|
bool hasUpdate();
|
||||||
virtual bool isCustom();
|
virtual bool isCustom() override;
|
||||||
|
|
||||||
|
VersionFilePtr getVersionFile();
|
||||||
|
|
||||||
private: /* methods */
|
private: /* methods */
|
||||||
void applyFileTo(InstanceVersion *version);
|
void applyFileTo(MinecraftProfile *version);
|
||||||
|
|
||||||
public: /* data */
|
public: /* data */
|
||||||
/// The URL that this version will be downloaded from. maybe.
|
/// The URL that this version will be downloaded from. maybe.
|
||||||
|
@ -25,12 +25,53 @@
|
|||||||
#include "logic/net/URLConstants.h"
|
#include "logic/net/URLConstants.h"
|
||||||
|
|
||||||
#include "ParseUtils.h"
|
#include "ParseUtils.h"
|
||||||
|
#include "ProfileUtils.h"
|
||||||
#include "VersionBuilder.h"
|
#include "VersionBuilder.h"
|
||||||
#include <logic/VersionFilterData.h>
|
#include "VersionFilterData.h"
|
||||||
|
|
||||||
#include <pathutils.h>
|
#include <pathutils.h>
|
||||||
|
|
||||||
static const char * localVersionCache = "versions/versions.dat";
|
static const char * localVersionCache = "versions/versions.dat";
|
||||||
|
|
||||||
|
class MCVListLoadTask : public Task
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit MCVListLoadTask(MinecraftVersionList *vlist);
|
||||||
|
virtual ~MCVListLoadTask() override{};
|
||||||
|
|
||||||
|
virtual void executeTask() override;
|
||||||
|
|
||||||
|
protected
|
||||||
|
slots:
|
||||||
|
void list_downloaded();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
QNetworkReply *vlistReply;
|
||||||
|
MinecraftVersionList *m_list;
|
||||||
|
MinecraftVersion *m_currentStable;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MCVListVersionUpdateTask : public Task
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit MCVListVersionUpdateTask(MinecraftVersionList *vlist, QString updatedVersion);
|
||||||
|
virtual ~MCVListVersionUpdateTask() override{};
|
||||||
|
virtual void executeTask() override;
|
||||||
|
|
||||||
|
protected
|
||||||
|
slots:
|
||||||
|
void json_downloaded();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
NetJobPtr specificVersionDownloadJob;
|
||||||
|
QString versionToUpdate;
|
||||||
|
MinecraftVersionList *m_list;
|
||||||
|
};
|
||||||
|
|
||||||
class ListLoadError : public MMCError
|
class ListLoadError : public MMCError
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -442,21 +483,9 @@ void MCVListVersionUpdateTask::json_downloaded()
|
|||||||
emitFailed(tr("Couldn't process version file: %1").arg(e.cause()));
|
emitFailed(tr("Couldn't process version file: %1").arg(e.cause()));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
QList<RawLibraryPtr> filteredLibs;
|
|
||||||
QList<RawLibraryPtr> lwjglLibs;
|
|
||||||
|
|
||||||
for (auto lib : file->overwriteLibs)
|
// Strip LWJGL from the version file. We use our own.
|
||||||
{
|
ProfileUtils::removeLwjglFromPatch(file);
|
||||||
if (g_VersionFilterData.lwjglWhitelist.contains(lib->artifactPrefix()))
|
|
||||||
{
|
|
||||||
lwjglLibs.append(lib);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
filteredLibs.append(lib);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
file->overwriteLibs = filteredLibs;
|
|
||||||
|
|
||||||
// TODO: recognize and add LWJGL versions here.
|
// TODO: recognize and add LWJGL versions here.
|
||||||
|
|
||||||
@ -593,3 +622,5 @@ void MinecraftVersionList::finalizeUpdate(QString version)
|
|||||||
|
|
||||||
saveCachedList();
|
saveCachedList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include "MinecraftVersionList.moc"
|
@ -26,7 +26,6 @@
|
|||||||
|
|
||||||
class MCVListLoadTask;
|
class MCVListLoadTask;
|
||||||
class MCVListVersionUpdateTask;
|
class MCVListVersionUpdateTask;
|
||||||
class QNetworkReply;
|
|
||||||
|
|
||||||
class MinecraftVersionList : public BaseVersionList
|
class MinecraftVersionList : public BaseVersionList
|
||||||
{
|
{
|
||||||
@ -67,42 +66,3 @@ protected
|
|||||||
slots:
|
slots:
|
||||||
virtual void updateListData(QList<BaseVersionPtr> versions);
|
virtual void updateListData(QList<BaseVersionPtr> versions);
|
||||||
};
|
};
|
||||||
|
|
||||||
class MCVListLoadTask : public Task
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit MCVListLoadTask(MinecraftVersionList *vlist);
|
|
||||||
virtual ~MCVListLoadTask() override{};
|
|
||||||
|
|
||||||
virtual void executeTask() override;
|
|
||||||
|
|
||||||
protected
|
|
||||||
slots:
|
|
||||||
void list_downloaded();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
QNetworkReply *vlistReply;
|
|
||||||
MinecraftVersionList *m_list;
|
|
||||||
MinecraftVersion *m_currentStable;
|
|
||||||
};
|
|
||||||
|
|
||||||
class MCVListVersionUpdateTask : public Task
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit MCVListVersionUpdateTask(MinecraftVersionList *vlist, QString updatedVersion);
|
|
||||||
virtual ~MCVListVersionUpdateTask() override{};
|
|
||||||
virtual void executeTask() override;
|
|
||||||
|
|
||||||
protected
|
|
||||||
slots:
|
|
||||||
void json_downloaded();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
NetJobPtr specificVersionDownloadJob;
|
|
||||||
QString versionToUpdate;
|
|
||||||
MinecraftVersionList *m_list;
|
|
||||||
};
|
|
||||||
|
24
logic/minecraft/NullProfileStrategy.h
Normal file
24
logic/minecraft/NullProfileStrategy.h
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "ProfileStrategy.h"
|
||||||
|
|
||||||
|
class NullProfileStrategy: public ProfileStrategy
|
||||||
|
{
|
||||||
|
virtual bool installJarMods(QStringList filepaths)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
virtual void load() {};
|
||||||
|
virtual bool removePatch(ProfilePatchPtr jarMod)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
virtual bool resetOrder()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
virtual bool saveOrder(ProfileUtils::PatchOrder order)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
@ -18,10 +18,6 @@
|
|||||||
#include "OneSixLibrary.h"
|
#include "OneSixLibrary.h"
|
||||||
#include "OneSixRule.h"
|
#include "OneSixRule.h"
|
||||||
#include "OpSys.h"
|
#include "OpSys.h"
|
||||||
#include "logic/net/URLConstants.h"
|
|
||||||
#include <pathutils.h>
|
|
||||||
#include <JlCompress.h>
|
|
||||||
#include "logger/QsLog.h"
|
|
||||||
|
|
||||||
OneSixLibrary::OneSixLibrary(RawLibraryPtr base)
|
OneSixLibrary::OneSixLibrary(RawLibraryPtr base)
|
||||||
{
|
{
|
||||||
|
270
logic/minecraft/OneSixProfileStrategy.cpp
Normal file
270
logic/minecraft/OneSixProfileStrategy.cpp
Normal file
@ -0,0 +1,270 @@
|
|||||||
|
#include "logic/minecraft/OneSixProfileStrategy.h"
|
||||||
|
#include "logic/minecraft/VersionBuildError.h"
|
||||||
|
#include "logic/OneSixInstance.h"
|
||||||
|
#include "logic/minecraft/MinecraftVersionList.h"
|
||||||
|
|
||||||
|
#include "MultiMC.h"
|
||||||
|
|
||||||
|
#include <pathutils.h>
|
||||||
|
#include <QDir>
|
||||||
|
#include <QUuid>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QJsonArray>
|
||||||
|
|
||||||
|
OneSixProfileStrategy::OneSixProfileStrategy(OneSixInstance* instance)
|
||||||
|
{
|
||||||
|
m_instance = instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OneSixProfileStrategy::upgradeDeprecatedFiles()
|
||||||
|
{
|
||||||
|
auto versionJsonPath = PathCombine(m_instance->instanceRoot(), "version.json");
|
||||||
|
auto customJsonPath = PathCombine(m_instance->instanceRoot(), "custom.json");
|
||||||
|
auto mcJson = PathCombine(m_instance->instanceRoot(), "patches" , "net.minecraft.json");
|
||||||
|
|
||||||
|
// convert old crap.
|
||||||
|
if(QFile::exists(customJsonPath))
|
||||||
|
{
|
||||||
|
if(!ensureFilePathExists(mcJson))
|
||||||
|
{
|
||||||
|
// WHAT DO???
|
||||||
|
}
|
||||||
|
if(!QFile::rename(customJsonPath, mcJson))
|
||||||
|
{
|
||||||
|
// WHAT DO???
|
||||||
|
}
|
||||||
|
if(QFile::exists(versionJsonPath))
|
||||||
|
{
|
||||||
|
if(!QFile::remove(versionJsonPath))
|
||||||
|
{
|
||||||
|
// WHAT DO???
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(QFile::exists(versionJsonPath))
|
||||||
|
{
|
||||||
|
if(!ensureFilePathExists(mcJson))
|
||||||
|
{
|
||||||
|
// WHAT DO???
|
||||||
|
}
|
||||||
|
if(!QFile::rename(versionJsonPath, mcJson))
|
||||||
|
{
|
||||||
|
// WHAT DO???
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void OneSixProfileStrategy::loadDefaultBuiltinPatches()
|
||||||
|
{
|
||||||
|
auto mcJson = PathCombine(m_instance->instanceRoot(), "patches" , "net.minecraft.json");
|
||||||
|
// load up the base minecraft patch
|
||||||
|
ProfilePatchPtr minecraftPatch;
|
||||||
|
if(QFile::exists(mcJson))
|
||||||
|
{
|
||||||
|
auto file = ProfileUtils::parseJsonFile(QFileInfo(mcJson), false);
|
||||||
|
file->fileId = "net.minecraft";
|
||||||
|
file->name = "Minecraft";
|
||||||
|
if(file->version.isEmpty())
|
||||||
|
{
|
||||||
|
file->version = m_instance->intendedVersionId();
|
||||||
|
}
|
||||||
|
minecraftPatch = std::dynamic_pointer_cast<ProfilePatch>(file);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto minecraftList = MMC->minecraftlist();
|
||||||
|
auto mcversion = minecraftList->findVersion(m_instance->intendedVersionId());
|
||||||
|
minecraftPatch = std::dynamic_pointer_cast<ProfilePatch>(mcversion);
|
||||||
|
}
|
||||||
|
if (!minecraftPatch)
|
||||||
|
{
|
||||||
|
throw VersionIncomplete("net.minecraft");
|
||||||
|
}
|
||||||
|
minecraftPatch->setOrder(-2);
|
||||||
|
profile->appendPatch(minecraftPatch);
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: this is obviously fake.
|
||||||
|
QResource LWJGL(":/versions/LWJGL/2.9.1.json");
|
||||||
|
auto lwjgl = ProfileUtils::parseJsonFile(LWJGL.absoluteFilePath(), false, false);
|
||||||
|
auto lwjglPatch = std::dynamic_pointer_cast<ProfilePatch>(lwjgl);
|
||||||
|
if (!lwjglPatch)
|
||||||
|
{
|
||||||
|
throw VersionIncomplete("org.lwjgl");
|
||||||
|
}
|
||||||
|
lwjglPatch->setOrder(-1);
|
||||||
|
lwjgl->setVanilla(true);
|
||||||
|
profile->appendPatch(lwjglPatch);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OneSixProfileStrategy::loadUserPatches()
|
||||||
|
{
|
||||||
|
// load all patches, put into map for ordering, apply in the right order
|
||||||
|
ProfileUtils::PatchOrder userOrder;
|
||||||
|
ProfileUtils::readOverrideOrders(PathCombine(m_instance->instanceRoot(), "order.json"), userOrder);
|
||||||
|
QDir patches(PathCombine(m_instance->instanceRoot(),"patches"));
|
||||||
|
|
||||||
|
// first, load things by sort order.
|
||||||
|
for (auto id : userOrder)
|
||||||
|
{
|
||||||
|
// ignore builtins
|
||||||
|
if (id == "net.minecraft")
|
||||||
|
continue;
|
||||||
|
if (id == "org.lwjgl")
|
||||||
|
continue;
|
||||||
|
// parse the file
|
||||||
|
QString filename = patches.absoluteFilePath(id + ".json");
|
||||||
|
QFileInfo finfo(filename);
|
||||||
|
if(!finfo.exists())
|
||||||
|
{
|
||||||
|
QLOG_INFO() << "Patch file " << filename << " was deleted by external means...";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
QLOG_INFO() << "Reading" << filename << "by user order";
|
||||||
|
auto file = ProfileUtils::parseJsonFile(finfo, false);
|
||||||
|
// sanity check. prevent tampering with files.
|
||||||
|
if (file->fileId != id)
|
||||||
|
{
|
||||||
|
throw VersionBuildError(
|
||||||
|
QObject::tr("load id %1 does not match internal id %2").arg(id, file->fileId));
|
||||||
|
}
|
||||||
|
profile->appendPatch(file);
|
||||||
|
}
|
||||||
|
// now load the rest by internal preference.
|
||||||
|
QMap<int, QPair<QString, VersionFilePtr>> files;
|
||||||
|
for (auto info : patches.entryInfoList(QStringList() << "*.json", QDir::Files))
|
||||||
|
{
|
||||||
|
// parse the file
|
||||||
|
QLOG_INFO() << "Reading" << info.fileName();
|
||||||
|
auto file = ProfileUtils::parseJsonFile(info, true);
|
||||||
|
// ignore builtins
|
||||||
|
if (file->fileId == "net.minecraft")
|
||||||
|
continue;
|
||||||
|
if (file->fileId == "org.lwjgl")
|
||||||
|
continue;
|
||||||
|
// do not load what we already loaded in the first pass
|
||||||
|
if (userOrder.contains(file->fileId))
|
||||||
|
continue;
|
||||||
|
if (files.contains(file->order))
|
||||||
|
{
|
||||||
|
// FIXME: do not throw?
|
||||||
|
throw VersionBuildError(QObject::tr("%1 has the same order as %2")
|
||||||
|
.arg(file->fileId, files[file->order].second->fileId));
|
||||||
|
}
|
||||||
|
files.insert(file->order, qMakePair(info.fileName(), file));
|
||||||
|
}
|
||||||
|
for (auto order : files.keys())
|
||||||
|
{
|
||||||
|
auto &filePair = files[order];
|
||||||
|
profile->appendPatch(filePair.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void OneSixProfileStrategy::load()
|
||||||
|
{
|
||||||
|
profile->clearPatches();
|
||||||
|
|
||||||
|
upgradeDeprecatedFiles();
|
||||||
|
loadDefaultBuiltinPatches();
|
||||||
|
loadUserPatches();
|
||||||
|
|
||||||
|
profile->finalize();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OneSixProfileStrategy::saveOrder(ProfileUtils::PatchOrder order)
|
||||||
|
{
|
||||||
|
return ProfileUtils::writeOverrideOrders(PathCombine(m_instance->instanceRoot(), "order.json"), order);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OneSixProfileStrategy::resetOrder()
|
||||||
|
{
|
||||||
|
return QDir(m_instance->instanceRoot()).remove("order.json");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OneSixProfileStrategy::removePatch(ProfilePatchPtr patch)
|
||||||
|
{
|
||||||
|
bool ok = true;
|
||||||
|
// first, remove the patch file. this ensures it's not used anymore
|
||||||
|
auto fileName = patch->getPatchFilename();
|
||||||
|
|
||||||
|
|
||||||
|
auto preRemoveJarMod = [&](JarmodPtr jarMod) -> bool
|
||||||
|
{
|
||||||
|
QString fullpath = PathCombine(m_instance->jarModsDir(), jarMod->name);
|
||||||
|
QFileInfo finfo (fullpath);
|
||||||
|
if(finfo.exists())
|
||||||
|
{
|
||||||
|
return QFile::remove(fullpath);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
for(auto &jarmod: patch->getJarMods())
|
||||||
|
{
|
||||||
|
ok &= preRemoveJarMod(jarmod);
|
||||||
|
}
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OneSixProfileStrategy::installJarMods(QStringList filepaths)
|
||||||
|
{
|
||||||
|
QString patchDir = PathCombine(m_instance->instanceRoot(), "patches");
|
||||||
|
if(!ensureFolderPathExists(patchDir))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ensureFolderPathExists(m_instance->jarModsDir()))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(auto filepath:filepaths)
|
||||||
|
{
|
||||||
|
QFileInfo sourceInfo(filepath);
|
||||||
|
auto uuid = QUuid::createUuid();
|
||||||
|
QString id = uuid.toString().remove('{').remove('}');
|
||||||
|
QString target_filename = id + ".jar";
|
||||||
|
QString target_id = "org.multimc.jarmod." + id;
|
||||||
|
QString target_name = sourceInfo.completeBaseName() + " (jar mod)";
|
||||||
|
QString finalPath = PathCombine(m_instance->jarModsDir(), target_filename);
|
||||||
|
|
||||||
|
QFileInfo targetInfo(finalPath);
|
||||||
|
if(targetInfo.exists())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!QFile::copy(sourceInfo.absoluteFilePath(),QFileInfo(finalPath).absoluteFilePath()))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto f = std::make_shared<VersionFile>();
|
||||||
|
auto jarMod = std::make_shared<Jarmod>();
|
||||||
|
jarMod->name = target_filename;
|
||||||
|
f->jarMods.append(jarMod);
|
||||||
|
f->name = target_name;
|
||||||
|
f->fileId = target_id;
|
||||||
|
f->order = profile->getFreeOrderNumber();
|
||||||
|
QString patchFileName = PathCombine(patchDir, target_id + ".json");
|
||||||
|
f->filename = patchFileName;
|
||||||
|
|
||||||
|
QFile file(patchFileName);
|
||||||
|
if (!file.open(QFile::WriteOnly))
|
||||||
|
{
|
||||||
|
QLOG_ERROR() << "Error opening" << file.fileName()
|
||||||
|
<< "for reading:" << file.errorString();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
file.write(f->toJson(true).toJson());
|
||||||
|
file.close();
|
||||||
|
profile->appendPatch(f);
|
||||||
|
}
|
||||||
|
profile->saveCurrentOrder();
|
||||||
|
profile->reapply();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
24
logic/minecraft/OneSixProfileStrategy.h
Normal file
24
logic/minecraft/OneSixProfileStrategy.h
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "ProfileStrategy.h"
|
||||||
|
|
||||||
|
class OneSixInstance;
|
||||||
|
|
||||||
|
class OneSixProfileStrategy : public ProfileStrategy
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
OneSixProfileStrategy(OneSixInstance * instance);
|
||||||
|
virtual ~OneSixProfileStrategy() {};
|
||||||
|
virtual void load() override;
|
||||||
|
virtual bool resetOrder() override;
|
||||||
|
virtual bool saveOrder(ProfileUtils::PatchOrder order) override;
|
||||||
|
virtual bool installJarMods(QStringList filepaths) override;
|
||||||
|
virtual bool removePatch(ProfilePatchPtr patch) override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void loadDefaultBuiltinPatches();
|
||||||
|
void loadUserPatches();
|
||||||
|
void upgradeDeprecatedFiles();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
OneSixInstance *m_instance;
|
||||||
|
};
|
@ -4,12 +4,12 @@
|
|||||||
#include <QList>
|
#include <QList>
|
||||||
#include "JarMod.h"
|
#include "JarMod.h"
|
||||||
|
|
||||||
class InstanceVersion;
|
class MinecraftProfile;
|
||||||
class VersionPatch
|
class ProfilePatch
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~VersionPatch(){};
|
virtual ~ProfilePatch(){};
|
||||||
virtual void applyTo(InstanceVersion *version) = 0;
|
virtual void applyTo(MinecraftProfile *version) = 0;
|
||||||
|
|
||||||
virtual bool isMinecraftVersion() = 0;
|
virtual bool isMinecraftVersion() = 0;
|
||||||
virtual bool hasJarMods() = 0;
|
virtual bool hasJarMods() = 0;
|
||||||
@ -29,4 +29,4 @@ public:
|
|||||||
virtual bool isCustom() = 0;
|
virtual bool isCustom() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::shared_ptr<VersionPatch> VersionPatchPtr;
|
typedef std::shared_ptr<ProfilePatch> ProfilePatchPtr;
|
30
logic/minecraft/ProfileStrategy.h
Normal file
30
logic/minecraft/ProfileStrategy.h
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "ProfileUtils.h"
|
||||||
|
|
||||||
|
class MinecraftProfile;
|
||||||
|
|
||||||
|
class ProfileStrategy
|
||||||
|
{
|
||||||
|
friend class MinecraftProfile;
|
||||||
|
public:
|
||||||
|
virtual ~ProfileStrategy(){};
|
||||||
|
|
||||||
|
/// load the patch files into the profile
|
||||||
|
virtual void load() = 0;
|
||||||
|
|
||||||
|
/// reset the order of patches
|
||||||
|
virtual bool resetOrder() = 0;
|
||||||
|
|
||||||
|
/// save the order of patches, given the order
|
||||||
|
virtual bool saveOrder(ProfileUtils::PatchOrder order) = 0;
|
||||||
|
|
||||||
|
/// install a list of jar mods into the instance
|
||||||
|
virtual bool installJarMods(QStringList filepaths) = 0;
|
||||||
|
|
||||||
|
/// remove any files or records that constitute the version patch
|
||||||
|
virtual bool removePatch(ProfilePatchPtr jarMod) = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
MinecraftProfile *profile;
|
||||||
|
};
|
145
logic/minecraft/ProfileUtils.cpp
Normal file
145
logic/minecraft/ProfileUtils.cpp
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
#include "ProfileUtils.h"
|
||||||
|
#include "logic/minecraft/VersionFilterData.h"
|
||||||
|
#include "logic/MMCJson.h"
|
||||||
|
#include "logger/QsLog.h"
|
||||||
|
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QJsonArray>
|
||||||
|
#include <QRegularExpression>
|
||||||
|
|
||||||
|
namespace ProfileUtils
|
||||||
|
{
|
||||||
|
|
||||||
|
static const int currentOrderFileVersion = 1;
|
||||||
|
|
||||||
|
bool writeOverrideOrders(QString path, const PatchOrder &order)
|
||||||
|
{
|
||||||
|
QJsonObject obj;
|
||||||
|
obj.insert("version", currentOrderFileVersion);
|
||||||
|
QJsonArray orderArray;
|
||||||
|
for(auto str: order)
|
||||||
|
{
|
||||||
|
orderArray.append(str);
|
||||||
|
}
|
||||||
|
obj.insert("order", orderArray);
|
||||||
|
QFile orderFile(path);
|
||||||
|
if (!orderFile.open(QFile::WriteOnly))
|
||||||
|
{
|
||||||
|
QLOG_ERROR() << "Couldn't open" << orderFile.fileName()
|
||||||
|
<< "for writing:" << orderFile.errorString();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
orderFile.write(QJsonDocument(obj).toJson(QJsonDocument::Indented));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool readOverrideOrders(QString path, PatchOrder &order)
|
||||||
|
{
|
||||||
|
QFile orderFile(path);
|
||||||
|
if (!orderFile.exists())
|
||||||
|
{
|
||||||
|
QLOG_WARN() << "Order file doesn't exist. Ignoring.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!orderFile.open(QFile::ReadOnly))
|
||||||
|
{
|
||||||
|
QLOG_ERROR() << "Couldn't open" << orderFile.fileName()
|
||||||
|
<< " for reading:" << orderFile.errorString();
|
||||||
|
QLOG_WARN() << "Ignoring overriden order";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// and it's valid JSON
|
||||||
|
QJsonParseError error;
|
||||||
|
QJsonDocument doc = QJsonDocument::fromJson(orderFile.readAll(), &error);
|
||||||
|
if (error.error != QJsonParseError::NoError)
|
||||||
|
{
|
||||||
|
QLOG_ERROR() << "Couldn't parse" << orderFile.fileName() << ":" << error.errorString();
|
||||||
|
QLOG_WARN() << "Ignoring overriden order";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// and then read it and process it if all above is true.
|
||||||
|
try
|
||||||
|
{
|
||||||
|
auto obj = MMCJson::ensureObject(doc);
|
||||||
|
// check order file version.
|
||||||
|
auto version = MMCJson::ensureInteger(obj.value("version"), "version");
|
||||||
|
if (version != currentOrderFileVersion)
|
||||||
|
{
|
||||||
|
throw JSONValidationError(QObject::tr("Invalid order file version, expected %1")
|
||||||
|
.arg(currentOrderFileVersion));
|
||||||
|
}
|
||||||
|
auto orderArray = MMCJson::ensureArray(obj.value("order"));
|
||||||
|
for(auto item: orderArray)
|
||||||
|
{
|
||||||
|
order.append(MMCJson::ensureString(item));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (JSONValidationError &err)
|
||||||
|
{
|
||||||
|
QLOG_ERROR() << "Couldn't parse" << orderFile.fileName() << ": bad file format";
|
||||||
|
QLOG_WARN() << "Ignoring overriden order";
|
||||||
|
order.clear();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
VersionFilePtr parseJsonFile(const QFileInfo &fileInfo, const bool requireOrder, bool isFTB)
|
||||||
|
{
|
||||||
|
QFile file(fileInfo.absoluteFilePath());
|
||||||
|
if (!file.open(QFile::ReadOnly))
|
||||||
|
{
|
||||||
|
throw JSONValidationError(QObject::tr("Unable to open the version file %1: %2.")
|
||||||
|
.arg(fileInfo.fileName(), file.errorString()));
|
||||||
|
}
|
||||||
|
QJsonParseError error;
|
||||||
|
QJsonDocument doc = QJsonDocument::fromJson(file.readAll(), &error);
|
||||||
|
if (error.error != QJsonParseError::NoError)
|
||||||
|
{
|
||||||
|
throw JSONValidationError(
|
||||||
|
QObject::tr("Unable to process the version file %1: %2 at %3.")
|
||||||
|
.arg(fileInfo.fileName(), error.errorString())
|
||||||
|
.arg(error.offset));
|
||||||
|
}
|
||||||
|
return VersionFile::fromJson(doc, file.fileName(), requireOrder, isFTB);
|
||||||
|
}
|
||||||
|
|
||||||
|
VersionFilePtr parseBinaryJsonFile(const QFileInfo &fileInfo)
|
||||||
|
{
|
||||||
|
QFile file(fileInfo.absoluteFilePath());
|
||||||
|
if (!file.open(QFile::ReadOnly))
|
||||||
|
{
|
||||||
|
throw JSONValidationError(QObject::tr("Unable to open the version file %1: %2.")
|
||||||
|
.arg(fileInfo.fileName(), file.errorString()));
|
||||||
|
}
|
||||||
|
QJsonDocument doc = QJsonDocument::fromBinaryData(file.readAll());
|
||||||
|
file.close();
|
||||||
|
if (doc.isNull())
|
||||||
|
{
|
||||||
|
file.remove();
|
||||||
|
throw JSONValidationError(
|
||||||
|
QObject::tr("Unable to process the version file %1.").arg(fileInfo.fileName()));
|
||||||
|
}
|
||||||
|
return VersionFile::fromJson(doc, file.fileName(), false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void removeLwjglFromPatch(VersionFilePtr patch)
|
||||||
|
{
|
||||||
|
auto filter = [](QList<RawLibraryPtr>& libs)
|
||||||
|
{
|
||||||
|
QList<RawLibraryPtr> filteredLibs;
|
||||||
|
for (auto lib : libs)
|
||||||
|
{
|
||||||
|
if (!g_VersionFilterData.lwjglWhitelist.contains(lib->artifactPrefix()))
|
||||||
|
{
|
||||||
|
filteredLibs.append(lib);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
libs = filteredLibs;
|
||||||
|
};
|
||||||
|
filter(patch->addLibs);
|
||||||
|
filter(patch->overwriteLibs);
|
||||||
|
}
|
||||||
|
}
|
25
logic/minecraft/ProfileUtils.h
Normal file
25
logic/minecraft/ProfileUtils.h
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "RawLibrary.h"
|
||||||
|
#include "VersionFile.h"
|
||||||
|
|
||||||
|
namespace ProfileUtils
|
||||||
|
{
|
||||||
|
typedef QStringList PatchOrder;
|
||||||
|
|
||||||
|
/// Read and parse a OneSix format order file
|
||||||
|
bool readOverrideOrders(QString path, PatchOrder &order);
|
||||||
|
|
||||||
|
/// Write a OneSix format order file
|
||||||
|
bool writeOverrideOrders(QString path, const PatchOrder &order);
|
||||||
|
|
||||||
|
|
||||||
|
/// Parse a version file in JSON format
|
||||||
|
VersionFilePtr parseJsonFile(const QFileInfo &fileInfo, const bool requireOrder, bool isFTB = false);
|
||||||
|
|
||||||
|
/// Parse a version file in binary JSON format
|
||||||
|
VersionFilePtr parseBinaryJsonFile(const QFileInfo &fileInfo);
|
||||||
|
|
||||||
|
/// Remove LWJGL from a patch file. This is applied to all Mojang-like profile files.
|
||||||
|
void removeLwjglFromPatch(VersionFilePtr patch);
|
||||||
|
|
||||||
|
}
|
@ -24,15 +24,17 @@
|
|||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <qresource.h>
|
#include <qresource.h>
|
||||||
#include <modutils.h>
|
#include <modutils.h>
|
||||||
|
#include <pathutils.h>
|
||||||
|
|
||||||
#include "MultiMC.h"
|
#include "MultiMC.h"
|
||||||
#include "logic/minecraft/VersionBuilder.h"
|
#include "logic/minecraft/VersionBuilder.h"
|
||||||
#include "logic/minecraft/InstanceVersion.h"
|
#include "logic/minecraft/MinecraftProfile.h"
|
||||||
#include "logic/minecraft/OneSixRule.h"
|
#include "logic/minecraft/OneSixRule.h"
|
||||||
#include "logic/minecraft/VersionPatch.h"
|
#include "logic/minecraft/ProfilePatch.h"
|
||||||
#include "logic/minecraft/VersionFile.h"
|
#include "logic/minecraft/VersionFile.h"
|
||||||
#include "VersionBuildError.h"
|
#include "VersionBuildError.h"
|
||||||
#include "MinecraftVersionList.h"
|
#include "MinecraftVersionList.h"
|
||||||
|
#include "ProfileUtils.h"
|
||||||
|
|
||||||
#include "logic/OneSixInstance.h"
|
#include "logic/OneSixInstance.h"
|
||||||
#include "logic/MMCJson.h"
|
#include "logic/MMCJson.h"
|
||||||
@ -43,17 +45,15 @@ VersionBuilder::VersionBuilder()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void VersionBuilder::build(InstanceVersion *version, OneSixInstance *instance,
|
void VersionBuilder::build(MinecraftProfile *version, OneSixInstance *instance)
|
||||||
const QStringList &external)
|
|
||||||
{
|
{
|
||||||
VersionBuilder builder;
|
VersionBuilder builder;
|
||||||
builder.m_version = version;
|
builder.m_version = version;
|
||||||
builder.m_instance = instance;
|
builder.m_instance = instance;
|
||||||
builder.external_patches = external;
|
|
||||||
builder.buildInternal();
|
builder.buildInternal();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VersionBuilder::readJsonAndApplyToVersion(InstanceVersion *version, const QJsonObject &obj)
|
void VersionBuilder::readJsonAndApplyToVersion(MinecraftProfile *version, const QJsonObject &obj)
|
||||||
{
|
{
|
||||||
VersionBuilder builder;
|
VersionBuilder builder;
|
||||||
builder.m_version = version;
|
builder.m_version = version;
|
||||||
@ -61,178 +61,6 @@ void VersionBuilder::readJsonAndApplyToVersion(InstanceVersion *version, const Q
|
|||||||
builder.readJsonAndApply(obj);
|
builder.readJsonAndApply(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VersionBuilder::buildFromCustomJson()
|
|
||||||
{
|
|
||||||
QLOG_INFO() << "Building version from custom.json within the instance.";
|
|
||||||
QLOG_INFO() << "Reading custom.json";
|
|
||||||
auto file = parseJsonFile(QFileInfo(instance_root.absoluteFilePath("custom.json")), false);
|
|
||||||
file->name = "custom.json";
|
|
||||||
file->filename = "custom.json";
|
|
||||||
file->fileId = "org.multimc.custom.json";
|
|
||||||
file->order = -1;
|
|
||||||
file->version = QString();
|
|
||||||
m_version->VersionPatches.append(file);
|
|
||||||
m_version->finalize();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void VersionBuilder::buildFromVersionJson()
|
|
||||||
{
|
|
||||||
QLOG_INFO() << "Building version from version.json and patches within the instance.";
|
|
||||||
QLOG_INFO() << "Reading version.json";
|
|
||||||
auto file = parseJsonFile(QFileInfo(instance_root.absoluteFilePath("version.json")), false);
|
|
||||||
file->name = "Minecraft";
|
|
||||||
file->fileId = "org.multimc.version.json";
|
|
||||||
file->order = -1;
|
|
||||||
file->version = m_instance->intendedVersionId();
|
|
||||||
file->mcVersion = m_instance->intendedVersionId();
|
|
||||||
m_version->VersionPatches.append(file);
|
|
||||||
|
|
||||||
// load all patches, put into map for ordering, apply in the right order
|
|
||||||
readInstancePatches();
|
|
||||||
|
|
||||||
// some final touches
|
|
||||||
m_version->finalize();
|
|
||||||
}
|
|
||||||
|
|
||||||
void VersionBuilder::readInstancePatches()
|
|
||||||
{
|
|
||||||
PatchOrder userOrder;
|
|
||||||
readOverrideOrders(m_instance, userOrder);
|
|
||||||
QDir patches(instance_root.absoluteFilePath("patches/"));
|
|
||||||
|
|
||||||
// first, load things by sort order.
|
|
||||||
for (auto id : userOrder)
|
|
||||||
{
|
|
||||||
// ignore builtins
|
|
||||||
if (id == "net.minecraft")
|
|
||||||
continue;
|
|
||||||
if (id == "org.lwjgl")
|
|
||||||
continue;
|
|
||||||
// parse the file
|
|
||||||
QString filename = patches.absoluteFilePath(id + ".json");
|
|
||||||
QFileInfo finfo(filename);
|
|
||||||
if(!finfo.exists())
|
|
||||||
{
|
|
||||||
QLOG_INFO() << "Patch file " << filename << " was deleted by external means...";
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
QLOG_INFO() << "Reading" << filename << "by user order";
|
|
||||||
auto file = parseJsonFile(finfo, false);
|
|
||||||
// sanity check. prevent tampering with files.
|
|
||||||
if (file->fileId != id)
|
|
||||||
{
|
|
||||||
throw VersionBuildError(
|
|
||||||
QObject::tr("load id %1 does not match internal id %2").arg(id, file->fileId));
|
|
||||||
}
|
|
||||||
m_version->VersionPatches.append(file);
|
|
||||||
}
|
|
||||||
// now load the rest by internal preference.
|
|
||||||
QMap<int, QPair<QString, VersionFilePtr>> files;
|
|
||||||
for (auto info : patches.entryInfoList(QStringList() << "*.json", QDir::Files))
|
|
||||||
{
|
|
||||||
// parse the file
|
|
||||||
QLOG_INFO() << "Reading" << info.fileName();
|
|
||||||
auto file = parseJsonFile(info, true);
|
|
||||||
// ignore builtins
|
|
||||||
if (file->fileId == "net.minecraft")
|
|
||||||
continue;
|
|
||||||
if (file->fileId == "org.lwjgl")
|
|
||||||
continue;
|
|
||||||
// do not load what we already loaded in the first pass
|
|
||||||
if (userOrder.contains(file->fileId))
|
|
||||||
continue;
|
|
||||||
if (files.contains(file->order))
|
|
||||||
{
|
|
||||||
// FIXME: do not throw?
|
|
||||||
throw VersionBuildError(QObject::tr("%1 has the same order as %2")
|
|
||||||
.arg(file->fileId, files[file->order].second->fileId));
|
|
||||||
}
|
|
||||||
files.insert(file->order, qMakePair(info.fileName(), file));
|
|
||||||
}
|
|
||||||
for (auto order : files.keys())
|
|
||||||
{
|
|
||||||
auto &filePair = files[order];
|
|
||||||
m_version->VersionPatches.append(filePair.second);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void VersionBuilder::buildFromExternalPatches()
|
|
||||||
{
|
|
||||||
QLOG_INFO() << "Building version from external files.";
|
|
||||||
int externalOrder = -1;
|
|
||||||
for (auto fileName : external_patches)
|
|
||||||
{
|
|
||||||
QLOG_INFO() << "Reading" << fileName;
|
|
||||||
auto file = parseJsonFile(QFileInfo(fileName), false, fileName.endsWith("pack.json"));
|
|
||||||
file->name = QFileInfo(fileName).fileName();
|
|
||||||
file->fileId = "org.multimc.external." + file->name;
|
|
||||||
file->order = (externalOrder += 1);
|
|
||||||
file->version = QString();
|
|
||||||
file->mcVersion = QString();
|
|
||||||
m_version->VersionPatches.append(file);
|
|
||||||
}
|
|
||||||
// some final touches
|
|
||||||
m_version->finalize();
|
|
||||||
}
|
|
||||||
|
|
||||||
void VersionBuilder::buildFromMultilayer()
|
|
||||||
{
|
|
||||||
QLOG_INFO() << "Building version from multilayered sources.";
|
|
||||||
// just the builtin stuff for now
|
|
||||||
auto minecraftList = MMC->minecraftlist();
|
|
||||||
auto mcversion = minecraftList->findVersion(m_instance->intendedVersionId());
|
|
||||||
auto minecraftPatch = std::dynamic_pointer_cast<VersionPatch>(mcversion);
|
|
||||||
if (!minecraftPatch)
|
|
||||||
{
|
|
||||||
throw VersionIncomplete("net.minecraft");
|
|
||||||
}
|
|
||||||
minecraftPatch->setOrder(-2);
|
|
||||||
m_version->VersionPatches.append(minecraftPatch);
|
|
||||||
|
|
||||||
// TODO: this is obviously fake.
|
|
||||||
QResource LWJGL(":/versions/LWJGL/2.9.1.json");
|
|
||||||
auto lwjgl = parseJsonFile(LWJGL.absoluteFilePath(), false, false);
|
|
||||||
auto lwjglPatch = std::dynamic_pointer_cast<VersionPatch>(lwjgl);
|
|
||||||
if (!lwjglPatch)
|
|
||||||
{
|
|
||||||
throw VersionIncomplete("org.lwjgl");
|
|
||||||
}
|
|
||||||
lwjglPatch->setOrder(-1);
|
|
||||||
lwjgl->setVanilla(true);
|
|
||||||
m_version->VersionPatches.append(lwjglPatch);
|
|
||||||
|
|
||||||
// load all patches, put into map for ordering, apply in the right order
|
|
||||||
readInstancePatches();
|
|
||||||
|
|
||||||
m_version->finalize();
|
|
||||||
}
|
|
||||||
|
|
||||||
void VersionBuilder::buildInternal()
|
|
||||||
{
|
|
||||||
m_version->VersionPatches.clear();
|
|
||||||
instance_root = QDir(m_instance->instanceRoot());
|
|
||||||
// if we do external files, do just those.
|
|
||||||
if (!external_patches.isEmpty())
|
|
||||||
{
|
|
||||||
buildFromExternalPatches();
|
|
||||||
}
|
|
||||||
// else, if there's custom json, we just do that.
|
|
||||||
else if (QFile::exists(instance_root.absoluteFilePath("custom.json")))
|
|
||||||
{
|
|
||||||
buildFromCustomJson();
|
|
||||||
}
|
|
||||||
// version.json -> patches/*.json
|
|
||||||
else if (QFile::exists(instance_root.absoluteFilePath("version.json")))
|
|
||||||
{
|
|
||||||
buildFromVersionJson();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
buildFromMultilayer();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void VersionBuilder::readJsonAndApply(const QJsonObject &obj)
|
void VersionBuilder::readJsonAndApply(const QJsonObject &obj)
|
||||||
{
|
{
|
||||||
m_version->clear();
|
m_version->clear();
|
||||||
@ -240,121 +68,17 @@ void VersionBuilder::readJsonAndApply(const QJsonObject &obj)
|
|||||||
auto file = VersionFile::fromJson(QJsonDocument(obj), QString(), false);
|
auto file = VersionFile::fromJson(QJsonDocument(obj), QString(), false);
|
||||||
|
|
||||||
file->applyTo(m_version);
|
file->applyTo(m_version);
|
||||||
m_version->VersionPatches.append(file);
|
m_version->appendPatch(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
VersionFilePtr VersionBuilder::parseJsonFile(const QFileInfo &fileInfo, const bool requireOrder,
|
|
||||||
bool isFTB)
|
void VersionBuilder::readInstancePatches()
|
||||||
{
|
{
|
||||||
QFile file(fileInfo.absoluteFilePath());
|
|
||||||
if (!file.open(QFile::ReadOnly))
|
|
||||||
{
|
|
||||||
throw JSONValidationError(QObject::tr("Unable to open the version file %1: %2.")
|
|
||||||
.arg(fileInfo.fileName(), file.errorString()));
|
|
||||||
}
|
|
||||||
QJsonParseError error;
|
|
||||||
QJsonDocument doc = QJsonDocument::fromJson(file.readAll(), &error);
|
|
||||||
if (error.error != QJsonParseError::NoError)
|
|
||||||
{
|
|
||||||
throw JSONValidationError(
|
|
||||||
QObject::tr("Unable to process the version file %1: %2 at %3.")
|
|
||||||
.arg(fileInfo.fileName(), error.errorString())
|
|
||||||
.arg(error.offset));
|
|
||||||
}
|
|
||||||
return VersionFile::fromJson(doc, file.fileName(), requireOrder, isFTB);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VersionFilePtr VersionBuilder::parseBinaryJsonFile(const QFileInfo &fileInfo)
|
void VersionBuilder::buildInternal()
|
||||||
{
|
{
|
||||||
QFile file(fileInfo.absoluteFilePath());
|
|
||||||
if (!file.open(QFile::ReadOnly))
|
|
||||||
{
|
|
||||||
throw JSONValidationError(QObject::tr("Unable to open the version file %1: %2.")
|
|
||||||
.arg(fileInfo.fileName(), file.errorString()));
|
|
||||||
}
|
|
||||||
QJsonDocument doc = QJsonDocument::fromBinaryData(file.readAll());
|
|
||||||
file.close();
|
|
||||||
if (doc.isNull())
|
|
||||||
{
|
|
||||||
file.remove();
|
|
||||||
throw JSONValidationError(
|
|
||||||
QObject::tr("Unable to process the version file %1.").arg(fileInfo.fileName()));
|
|
||||||
}
|
|
||||||
return VersionFile::fromJson(doc, file.fileName(), false, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const int currentOrderFileVersion = 1;
|
|
||||||
|
|
||||||
bool VersionBuilder::readOverrideOrders(OneSixInstance *instance, PatchOrder &order)
|
|
||||||
{
|
|
||||||
QFile orderFile(instance->instanceRoot() + "/order.json");
|
|
||||||
if (!orderFile.exists())
|
|
||||||
{
|
|
||||||
QLOG_WARN() << "Order file doesn't exist. Ignoring.";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!orderFile.open(QFile::ReadOnly))
|
|
||||||
{
|
|
||||||
QLOG_ERROR() << "Couldn't open" << orderFile.fileName()
|
|
||||||
<< " for reading:" << orderFile.errorString();
|
|
||||||
QLOG_WARN() << "Ignoring overriden order";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// and it's valid JSON
|
|
||||||
QJsonParseError error;
|
|
||||||
QJsonDocument doc = QJsonDocument::fromJson(orderFile.readAll(), &error);
|
|
||||||
if (error.error != QJsonParseError::NoError)
|
|
||||||
{
|
|
||||||
QLOG_ERROR() << "Couldn't parse" << orderFile.fileName() << ":" << error.errorString();
|
|
||||||
QLOG_WARN() << "Ignoring overriden order";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// and then read it and process it if all above is true.
|
|
||||||
try
|
|
||||||
{
|
|
||||||
auto obj = MMCJson::ensureObject(doc);
|
|
||||||
// check order file version.
|
|
||||||
auto version = MMCJson::ensureInteger(obj.value("version"), "version");
|
|
||||||
if (version != currentOrderFileVersion)
|
|
||||||
{
|
|
||||||
throw JSONValidationError(QObject::tr("Invalid order file version, expected %1")
|
|
||||||
.arg(currentOrderFileVersion));
|
|
||||||
}
|
|
||||||
auto orderArray = MMCJson::ensureArray(obj.value("order"));
|
|
||||||
for(auto item: orderArray)
|
|
||||||
{
|
|
||||||
order.append(MMCJson::ensureString(item));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (JSONValidationError &err)
|
|
||||||
{
|
|
||||||
QLOG_ERROR() << "Couldn't parse" << orderFile.fileName() << ": bad file format";
|
|
||||||
QLOG_WARN() << "Ignoring overriden order";
|
|
||||||
order.clear();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool VersionBuilder::writeOverrideOrders(OneSixInstance *instance, const PatchOrder &order)
|
|
||||||
{
|
|
||||||
QJsonObject obj;
|
|
||||||
obj.insert("version", currentOrderFileVersion);
|
|
||||||
QJsonArray orderArray;
|
|
||||||
for(auto str: order)
|
|
||||||
{
|
|
||||||
orderArray.append(str);
|
|
||||||
}
|
|
||||||
obj.insert("order", orderArray);
|
|
||||||
QFile orderFile(instance->instanceRoot() + "/order.json");
|
|
||||||
if (!orderFile.open(QFile::WriteOnly))
|
|
||||||
{
|
|
||||||
QLOG_ERROR() << "Couldn't open" << orderFile.fileName()
|
|
||||||
<< "for writing:" << orderFile.errorString();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
orderFile.write(QJsonDocument(obj).toJson(QJsonDocument::Indented));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
@ -19,36 +19,23 @@
|
|||||||
#include <QMap>
|
#include <QMap>
|
||||||
#include "VersionFile.h"
|
#include "VersionFile.h"
|
||||||
|
|
||||||
class InstanceVersion;
|
class MinecraftProfile;
|
||||||
class OneSixInstance;
|
class OneSixInstance;
|
||||||
class QJsonObject;
|
class QJsonObject;
|
||||||
class QFileInfo;
|
class QFileInfo;
|
||||||
|
|
||||||
typedef QStringList PatchOrder;
|
|
||||||
|
|
||||||
class VersionBuilder
|
class VersionBuilder
|
||||||
{
|
{
|
||||||
VersionBuilder();
|
VersionBuilder();
|
||||||
public:
|
public:
|
||||||
static void build(InstanceVersion *version, OneSixInstance *instance, const QStringList &external);
|
static void build(MinecraftProfile *version, OneSixInstance *instance);
|
||||||
static void readJsonAndApplyToVersion(InstanceVersion *version, const QJsonObject &obj);
|
static void readJsonAndApplyToVersion(MinecraftProfile *version, const QJsonObject &obj);
|
||||||
static VersionFilePtr parseJsonFile(const QFileInfo &fileInfo, const bool requireOrder, bool isFTB = false);
|
|
||||||
static VersionFilePtr parseBinaryJsonFile(const QFileInfo &fileInfo);
|
|
||||||
|
|
||||||
bool readOverrideOrders(OneSixInstance *instance, PatchOrder &order);
|
|
||||||
static bool writeOverrideOrders(OneSixInstance *instance, const PatchOrder &order);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
InstanceVersion *m_version;
|
MinecraftProfile *m_version;
|
||||||
OneSixInstance *m_instance;
|
OneSixInstance *m_instance;
|
||||||
QStringList external_patches;
|
|
||||||
QDir instance_root;
|
|
||||||
|
|
||||||
void buildInternal();
|
void buildInternal();
|
||||||
void buildFromExternalPatches();
|
|
||||||
void buildFromCustomJson();
|
|
||||||
void buildFromVersionJson();
|
|
||||||
void buildFromMultilayer();
|
|
||||||
|
|
||||||
void readInstancePatches();
|
void readInstancePatches();
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
#include "logic/minecraft/VersionFile.h"
|
#include "logic/minecraft/VersionFile.h"
|
||||||
#include "logic/minecraft/OneSixLibrary.h"
|
#include "logic/minecraft/OneSixLibrary.h"
|
||||||
#include "logic/minecraft/InstanceVersion.h"
|
#include "logic/minecraft/MinecraftProfile.h"
|
||||||
#include "logic/minecraft/JarMod.h"
|
#include "logic/minecraft/JarMod.h"
|
||||||
#include "ParseUtils.h"
|
#include "ParseUtils.h"
|
||||||
|
|
||||||
@ -256,8 +256,7 @@ QJsonDocument VersionFile::toJson(bool saveOrder)
|
|||||||
|
|
||||||
bool VersionFile::isMinecraftVersion()
|
bool VersionFile::isMinecraftVersion()
|
||||||
{
|
{
|
||||||
return (fileId == "org.multimc.version.json") || (fileId == "net.minecraft") ||
|
return fileId == "net.minecraft";
|
||||||
(fileId == "org.multimc.custom.json");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VersionFile::hasJarMods()
|
bool VersionFile::hasJarMods()
|
||||||
@ -265,7 +264,7 @@ bool VersionFile::hasJarMods()
|
|||||||
return !jarMods.isEmpty();
|
return !jarMods.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VersionFile::applyTo(InstanceVersion *version)
|
void VersionFile::applyTo(MinecraftProfile *version)
|
||||||
{
|
{
|
||||||
if (minimumLauncherVersion != -1)
|
if (minimumLauncherVersion != -1)
|
||||||
{
|
{
|
||||||
|
@ -6,23 +6,23 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include "logic/minecraft/OpSys.h"
|
#include "logic/minecraft/OpSys.h"
|
||||||
#include "logic/minecraft/OneSixRule.h"
|
#include "logic/minecraft/OneSixRule.h"
|
||||||
#include "VersionPatch.h"
|
#include "ProfilePatch.h"
|
||||||
#include "MMCError.h"
|
#include "MMCError.h"
|
||||||
#include "OneSixLibrary.h"
|
#include "OneSixLibrary.h"
|
||||||
#include "JarMod.h"
|
#include "JarMod.h"
|
||||||
|
|
||||||
class InstanceVersion;
|
class MinecraftProfile;
|
||||||
class VersionFile;
|
class VersionFile;
|
||||||
|
|
||||||
typedef std::shared_ptr<VersionFile> VersionFilePtr;
|
typedef std::shared_ptr<VersionFile> VersionFilePtr;
|
||||||
class VersionFile : public VersionPatch
|
class VersionFile : public ProfilePatch
|
||||||
{
|
{
|
||||||
public: /* methods */
|
public: /* methods */
|
||||||
static VersionFilePtr fromJson(const QJsonDocument &doc, const QString &filename,
|
static VersionFilePtr fromJson(const QJsonDocument &doc, const QString &filename,
|
||||||
const bool requireOrder, const bool isFTB = false);
|
const bool requireOrder, const bool isFTB = false);
|
||||||
QJsonDocument toJson(bool saveOrder);
|
QJsonDocument toJson(bool saveOrder);
|
||||||
|
|
||||||
virtual void applyTo(InstanceVersion *version) override;
|
virtual void applyTo(MinecraftProfile *version) override;
|
||||||
virtual bool isMinecraftVersion() override;
|
virtual bool isMinecraftVersion() override;
|
||||||
virtual bool hasJarMods() override;
|
virtual bool hasJarMods() override;
|
||||||
virtual int getOrder() override
|
virtual int getOrder() override
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#include "VersionFilterData.h"
|
#include "VersionFilterData.h"
|
||||||
#include "minecraft/ParseUtils.h"
|
#include "ParseUtils.h"
|
||||||
|
|
||||||
VersionFilterData g_VersionFilterData = VersionFilterData();
|
VersionFilterData g_VersionFilterData = VersionFilterData();
|
||||||
|
|
@ -3,8 +3,6 @@
|
|||||||
#include "logger/QsLog.h"
|
#include "logger/QsLog.h"
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
#include "gui/dialogs/CustomMessageBox.h"
|
|
||||||
#include <QDesktopServices>
|
|
||||||
|
|
||||||
PasteUpload::PasteUpload(QWidget *window, QString text) : m_window(window)
|
PasteUpload::PasteUpload(QWidget *window, QString text) : m_window(window)
|
||||||
{
|
{
|
||||||
|
@ -30,31 +30,6 @@ qint64 BaseExternalTool::pid(QProcess *process)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
QString BaseExternalTool::getSave() const
|
|
||||||
{
|
|
||||||
QDir saves(m_instance->minecraftRoot() + "/saves");
|
|
||||||
QStringList worlds = saves.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
|
|
||||||
QMutableListIterator<QString> it(worlds);
|
|
||||||
while (it.hasNext())
|
|
||||||
{
|
|
||||||
it.next();
|
|
||||||
if (!QDir(saves.absoluteFilePath(it.value())).exists("level.dat"))
|
|
||||||
{
|
|
||||||
it.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bool ok = true;
|
|
||||||
const QString save = QInputDialog::getItem(
|
|
||||||
MMC->activeWindow(), tr("MCEdit"), tr("Choose which world to open:"),
|
|
||||||
worlds, 0, false, &ok);
|
|
||||||
if (ok)
|
|
||||||
{
|
|
||||||
return saves.absoluteFilePath(save);
|
|
||||||
}
|
|
||||||
return QString();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BaseDetachedTool::BaseDetachedTool(InstancePtr instance, QObject *parent)
|
BaseDetachedTool::BaseDetachedTool(InstancePtr instance, QObject *parent)
|
||||||
: BaseExternalTool(instance, parent)
|
: BaseExternalTool(instance, parent)
|
||||||
{
|
{
|
||||||
|
@ -5,7 +5,6 @@
|
|||||||
|
|
||||||
class BaseInstance;
|
class BaseInstance;
|
||||||
class SettingsObject;
|
class SettingsObject;
|
||||||
class MinecraftProcess;
|
|
||||||
class QProcess;
|
class QProcess;
|
||||||
|
|
||||||
class BaseExternalTool : public QObject
|
class BaseExternalTool : public QObject
|
||||||
@ -19,7 +18,6 @@ protected:
|
|||||||
InstancePtr m_instance;
|
InstancePtr m_instance;
|
||||||
|
|
||||||
qint64 pid(QProcess *process);
|
qint64 pid(QProcess *process);
|
||||||
QString getSave() const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class BaseDetachedTool : public BaseExternalTool
|
class BaseDetachedTool : public BaseExternalTool
|
||||||
|
@ -7,7 +7,7 @@ BaseProfiler::BaseProfiler(InstancePtr instance, QObject *parent)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseProfiler::beginProfiling(MinecraftProcess *process)
|
void BaseProfiler::beginProfiling(BaseProcess *process)
|
||||||
{
|
{
|
||||||
beginProfilingImpl(process);
|
beginProfilingImpl(process);
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
class BaseInstance;
|
class BaseInstance;
|
||||||
class SettingsObject;
|
class SettingsObject;
|
||||||
class MinecraftProcess;
|
class BaseProcess;
|
||||||
class QProcess;
|
class QProcess;
|
||||||
|
|
||||||
class BaseProfiler : public BaseExternalTool
|
class BaseProfiler : public BaseExternalTool
|
||||||
@ -15,13 +15,13 @@ public:
|
|||||||
|
|
||||||
public
|
public
|
||||||
slots:
|
slots:
|
||||||
void beginProfiling(MinecraftProcess *process);
|
void beginProfiling(BaseProcess *process);
|
||||||
void abortProfiling();
|
void abortProfiling();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QProcess *m_profilerProcess;
|
QProcess *m_profilerProcess;
|
||||||
|
|
||||||
virtual void beginProfilingImpl(MinecraftProcess *process) = 0;
|
virtual void beginProfilingImpl(BaseProcess *process) = 0;
|
||||||
virtual void abortProfilingImpl();
|
virtual void abortProfilingImpl();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
|
|
||||||
#include "logic/settings/SettingsObject.h"
|
#include "logic/settings/SettingsObject.h"
|
||||||
#include "logic/MinecraftProcess.h"
|
#include "logic/BaseProcess.h"
|
||||||
#include "logic/BaseInstance.h"
|
#include "logic/BaseInstance.h"
|
||||||
#include "MultiMC.h"
|
#include "MultiMC.h"
|
||||||
|
|
||||||
@ -12,7 +12,7 @@ JProfiler::JProfiler(InstancePtr instance, QObject *parent) : BaseProfiler(insta
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void JProfiler::beginProfilingImpl(MinecraftProcess *process)
|
void JProfiler::beginProfilingImpl(BaseProcess *process)
|
||||||
{
|
{
|
||||||
int port = MMC->settings()->get("JProfilerPort").toInt();
|
int port = MMC->settings()->get("JProfilerPort").toInt();
|
||||||
QProcess *profiler = new QProcess(this);
|
QProcess *profiler = new QProcess(this);
|
||||||
|
@ -9,7 +9,7 @@ public:
|
|||||||
JProfiler(InstancePtr instance, QObject *parent = 0);
|
JProfiler(InstancePtr instance, QObject *parent = 0);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void beginProfilingImpl(MinecraftProcess *process);
|
void beginProfilingImpl(BaseProcess *process);
|
||||||
};
|
};
|
||||||
|
|
||||||
class JProfilerFactory : public BaseProfilerFactory
|
class JProfilerFactory : public BaseProfilerFactory
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
#include <QStandardPaths>
|
#include <QStandardPaths>
|
||||||
|
|
||||||
#include "logic/settings/SettingsObject.h"
|
#include "logic/settings/SettingsObject.h"
|
||||||
#include "logic/MinecraftProcess.h"
|
#include "logic/BaseProcess.h"
|
||||||
#include "logic/BaseInstance.h"
|
#include "logic/BaseInstance.h"
|
||||||
#include "MultiMC.h"
|
#include "MultiMC.h"
|
||||||
|
|
||||||
@ -12,7 +12,7 @@ JVisualVM::JVisualVM(InstancePtr instance, QObject *parent) : BaseProfiler(insta
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void JVisualVM::beginProfilingImpl(MinecraftProcess *process)
|
void JVisualVM::beginProfilingImpl(BaseProcess *process)
|
||||||
{
|
{
|
||||||
QProcess *profiler = new QProcess(this);
|
QProcess *profiler = new QProcess(this);
|
||||||
profiler->setArguments(QStringList() << "--openpid" << QString::number(pid(process)));
|
profiler->setArguments(QStringList() << "--openpid" << QString::number(pid(process)));
|
||||||
|
@ -9,7 +9,7 @@ public:
|
|||||||
JVisualVM(InstancePtr instance, QObject *parent = 0);
|
JVisualVM(InstancePtr instance, QObject *parent = 0);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void beginProfilingImpl(MinecraftProcess *process);
|
void beginProfilingImpl(BaseProcess *process);
|
||||||
};
|
};
|
||||||
|
|
||||||
class JVisualVMFactory : public BaseProfilerFactory
|
class JVisualVMFactory : public BaseProfilerFactory
|
||||||
|
@ -4,9 +4,12 @@
|
|||||||
#include <QProcess>
|
#include <QProcess>
|
||||||
#include <QDesktopServices>
|
#include <QDesktopServices>
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
|
// FIXME: mixing logic and UI!!!!
|
||||||
|
#include <QInputDialog>
|
||||||
|
|
||||||
#include "logic/settings/SettingsObject.h"
|
#include "logic/settings/SettingsObject.h"
|
||||||
#include "logic/BaseInstance.h"
|
#include "logic/BaseInstance.h"
|
||||||
|
#include "logic/minecraft/MinecraftInstance.h"
|
||||||
#include "MultiMC.h"
|
#include "MultiMC.h"
|
||||||
|
|
||||||
MCEditTool::MCEditTool(InstancePtr instance, QObject *parent)
|
MCEditTool::MCEditTool(InstancePtr instance, QObject *parent)
|
||||||
@ -14,6 +17,36 @@ MCEditTool::MCEditTool(InstancePtr instance, QObject *parent)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString MCEditTool::getSave() const
|
||||||
|
{
|
||||||
|
// FIXME: mixing logic and UI!!!!
|
||||||
|
auto mcInstance = std::dynamic_pointer_cast<MinecraftInstance>(m_instance);
|
||||||
|
if(!mcInstance)
|
||||||
|
{
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
QDir saves(mcInstance->minecraftRoot() + "/saves");
|
||||||
|
QStringList worlds = saves.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
|
||||||
|
QMutableListIterator<QString> it(worlds);
|
||||||
|
while (it.hasNext())
|
||||||
|
{
|
||||||
|
it.next();
|
||||||
|
if (!QDir(saves.absoluteFilePath(it.value())).exists("level.dat"))
|
||||||
|
{
|
||||||
|
it.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool ok = true;
|
||||||
|
const QString save = QInputDialog::getItem(
|
||||||
|
MMC->activeWindow(), tr("MCEdit"), tr("Choose which world to open:"),
|
||||||
|
worlds, 0, false, &ok);
|
||||||
|
if (ok)
|
||||||
|
{
|
||||||
|
return saves.absoluteFilePath(save);
|
||||||
|
}
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
void MCEditTool::runImpl()
|
void MCEditTool::runImpl()
|
||||||
{
|
{
|
||||||
const QString mceditPath = MMC->settings()->get("MCEditPath").toString();
|
const QString mceditPath = MMC->settings()->get("MCEditPath").toString();
|
||||||
|
@ -9,6 +9,7 @@ public:
|
|||||||
explicit MCEditTool(InstancePtr instance, QObject *parent = 0);
|
explicit MCEditTool(InstancePtr instance, QObject *parent = 0);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
QString getSave() const;
|
||||||
void runImpl() override;
|
void runImpl() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
1
main.cpp
1
main.cpp
@ -9,7 +9,6 @@ int main_gui(MultiMC &app)
|
|||||||
mainWin.restoreState(QByteArray::fromBase64(MMC->settings()->get("MainWindowState").toByteArray()));
|
mainWin.restoreState(QByteArray::fromBase64(MMC->settings()->get("MainWindowState").toByteArray()));
|
||||||
mainWin.restoreGeometry(QByteArray::fromBase64(MMC->settings()->get("MainWindowGeometry").toByteArray()));
|
mainWin.restoreGeometry(QByteArray::fromBase64(MMC->settings()->get("MainWindowGeometry").toByteArray()));
|
||||||
mainWin.show();
|
mainWin.show();
|
||||||
mainWin.checkMigrateLegacyAssets();
|
|
||||||
mainWin.checkSetDefaultJava();
|
mainWin.checkSetDefaultJava();
|
||||||
mainWin.checkInstancePathForProblems();
|
mainWin.checkInstancePathForProblems();
|
||||||
return app.exec();
|
return app.exec();
|
||||||
|
Loading…
Reference in New Issue
Block a user