summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt8
-rw-r--r--MultiMC.cpp3
-rw-r--r--changelog.md3
-rw-r--r--gui/dialogs/IconPickerDialog.h3
-rw-r--r--gui/dialogs/ProgressDialog.h3
-rw-r--r--gui/dialogs/SettingsDialog.cpp6
-rw-r--r--gui/dialogs/SettingsDialog.ui55
-rw-r--r--gui/pages/InstanceSettingsPage.ui24
-rw-r--r--logic/BaseVersionList.h3
-rw-r--r--logic/DefaultVariable.h35
-rw-r--r--logic/InstanceList.cpp24
-rw-r--r--logic/VersionFilterData.cpp4
-rw-r--r--logic/VersionFilterData.h2
-rw-r--r--logic/forge/ForgeInstaller.cpp35
-rw-r--r--logic/forge/ForgeVersion.h7
-rw-r--r--logic/forge/ForgeVersionList.cpp6
-rw-r--r--logic/liteloader/LiteLoaderVersionList.cpp2
-rw-r--r--logic/minecraft/GradleSpecifier.h129
-rw-r--r--logic/minecraft/MinecraftVersion.cpp14
-rw-r--r--logic/minecraft/MinecraftVersion.h10
-rw-r--r--logic/minecraft/MinecraftVersionList.cpp24
-rw-r--r--logic/minecraft/OneSixLibrary.cpp54
-rw-r--r--logic/minecraft/RawLibrary.cpp47
-rw-r--r--logic/minecraft/RawLibrary.h12
-rw-r--r--logic/minecraft/VersionFile.cpp29
-rw-r--r--tests/CMakeLists.txt1
-rw-r--r--tests/tst_gradlespecifier.cpp77
27 files changed, 498 insertions, 122 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 46446541..ac497f46 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -103,8 +103,8 @@ set(MultiMC_NEWS_RSS_URL "http://multimc.org/rss.xml" CACHE STRING "URL to fetch
######## Set version numbers ########
set(MultiMC_VERSION_MAJOR 0)
-set(MultiMC_VERSION_MINOR 4)
-set(MultiMC_VERSION_HOTFIX 1)
+set(MultiMC_VERSION_MINOR 5)
+set(MultiMC_VERSION_HOTFIX 0)
# Build number
set(MultiMC_VERSION_BUILD -1 CACHE STRING "Build number. -1 for no build number.")
@@ -427,6 +427,9 @@ SET(MULTIMC_SOURCES
# RW lock protected map
logic/RWStorage.h
+ # A variable that has an implicit default value and keeps track of changes
+ logic/DefaultVariable.h
+
# network stuffs
logic/net/NetAction.h
logic/net/MD5EtagDownload.h
@@ -493,6 +496,7 @@ SET(MULTIMC_SOURCES
logic/OneSixInstance_p.h
# OneSix version json infrastructure
+ logic/minecraft/GradleSpecifier.h
logic/minecraft/InstanceVersion.cpp
logic/minecraft/InstanceVersion.h
logic/minecraft/JarMod.cpp
diff --git a/MultiMC.cpp b/MultiMC.cpp
index 7e7c6c88..acf05c89 100644
--- a/MultiMC.cpp
+++ b/MultiMC.cpp
@@ -357,6 +357,9 @@ void MultiMC::initGlobalSettings()
m_settings->registerSetting("AutoUpdate", true);
m_settings->registerSetting("IconTheme", QString("multimc"));
+ // Minecraft Sneaky Updates
+ m_settings->registerSetting("AutoUpdateMinecraftVersions", true);
+
// Notifications
m_settings->registerSetting("ShownNotifications", QString());
diff --git a/changelog.md b/changelog.md
index e4da86b6..8bbade3e 100644
--- a/changelog.md
+++ b/changelog.md
@@ -1,5 +1,8 @@
#MultiMC Changelog
+##0.5.0
+- In development...
+
##0.4.1
- Fix LWJGL version list (SourceForge has changed the download API)
diff --git a/gui/dialogs/IconPickerDialog.h b/gui/dialogs/IconPickerDialog.h
index 70951da6..f00c2388 100644
--- a/gui/dialogs/IconPickerDialog.h
+++ b/gui/dialogs/IconPickerDialog.h
@@ -29,10 +29,7 @@ class IconPickerDialog : public QDialog
public:
explicit IconPickerDialog(QWidget *parent = 0);
~IconPickerDialog();
- #pragma clang diagnostic push
- #pragma clang diagnostic ignored "-Woverloaded-virtual"
int exec(QString selection);
- #pragma clang diagnostic pop
QString selectedIconKey;
protected:
diff --git a/gui/dialogs/ProgressDialog.h b/gui/dialogs/ProgressDialog.h
index 45a6238a..3276fd7a 100644
--- a/gui/dialogs/ProgressDialog.h
+++ b/gui/dialogs/ProgressDialog.h
@@ -34,10 +34,7 @@ public:
void updateSize();
- #pragma clang diagnostic push
- #pragma clang diagnostic ignored "-Woverloaded-virtual"
int exec(ProgressProvider *task);
- #pragma clang diagnostic pop
void setSkipButton(bool present, QString label = QString());
diff --git a/gui/dialogs/SettingsDialog.cpp b/gui/dialogs/SettingsDialog.cpp
index 46368bc1..347cd67e 100644
--- a/gui/dialogs/SettingsDialog.cpp
+++ b/gui/dialogs/SettingsDialog.cpp
@@ -365,6 +365,9 @@ void SettingsDialog::applySettings(SettingsObject *s)
}
s->set("JsonEditor", jsonEditor);
+ // Minecraft version updates
+ s->set("AutoUpdateMinecraftVersions", ui->autoupdateMinecraft->isChecked());
+
// Console
s->set("ShowConsole", ui->showConsoleCheck->isChecked());
s->set("AutoCloseConsole", ui->autoCloseConsoleCheck->isChecked());
@@ -470,6 +473,9 @@ void SettingsDialog::loadSettings(SettingsObject *s)
// Editors
ui->jsonEditorTextBox->setText(s->get("JsonEditor").toString());
+ // Minecraft version updates
+ ui->autoupdateMinecraft->setChecked(s->get("AutoUpdateMinecraftVersions").toBool());
+
// Console
ui->showConsoleCheck->setChecked(s->get("ShowConsole").toBool());
ui->autoCloseConsoleCheck->setChecked(s->get("AutoCloseConsole").toBool());
diff --git a/gui/dialogs/SettingsDialog.ui b/gui/dialogs/SettingsDialog.ui
index d4e90302..94b81dd7 100644
--- a/gui/dialogs/SettingsDialog.ui
+++ b/gui/dialogs/SettingsDialog.ui
@@ -410,6 +410,22 @@
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
+ <widget class="QGroupBox" name="groupBox_5">
+ <property name="title">
+ <string>Minecraft Version Updates</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_14">
+ <item>
+ <widget class="QCheckBox" name="autoupdateMinecraft">
+ <property name="text">
+ <string>Automatically update to latest version revision</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
<widget class="QGroupBox" name="windowSizeGroupBox">
<property name="title">
<string>Window Size</string>
@@ -1056,11 +1072,30 @@
</layout>
</widget>
<tabstops>
- <tabstop>buttonBox</tabstop>
+ <tabstop>settingsTabs</tabstop>
+ <tabstop>autoUpdateCheckBox</tabstop>
+ <tabstop>updateChannelComboBox</tabstop>
+ <tabstop>trackFtbBox</tabstop>
+ <tabstop>ftbLauncherBox</tabstop>
+ <tabstop>ftbLauncherBrowseBtn</tabstop>
+ <tabstop>ftbBox</tabstop>
+ <tabstop>ftbBrowseBtn</tabstop>
+ <tabstop>instDirTextBox</tabstop>
+ <tabstop>instDirBrowseBtn</tabstop>
+ <tabstop>modsDirTextBox</tabstop>
+ <tabstop>modsDirBrowseBtn</tabstop>
+ <tabstop>lwjglDirTextBox</tabstop>
+ <tabstop>lwjglDirBrowseBtn</tabstop>
+ <tabstop>iconsDirTextBox</tabstop>
+ <tabstop>iconsDirBrowseBtn</tabstop>
+ <tabstop>languageBox</tabstop>
+ <tabstop>resetNotificationsBtn</tabstop>
<tabstop>sortLastLaunchedBtn</tabstop>
<tabstop>sortByNameBtn</tabstop>
+ <tabstop>themeComboBox</tabstop>
<tabstop>jsonEditorTextBox</tabstop>
<tabstop>jsonEditorBrowseBtn</tabstop>
+ <tabstop>autoupdateMinecraft</tabstop>
<tabstop>maximizedCheckBox</tabstop>
<tabstop>windowWidthSpinBox</tabstop>
<tabstop>windowHeightSpinBox</tabstop>
@@ -1076,7 +1111,23 @@
<tabstop>jvmArgsTextBox</tabstop>
<tabstop>preLaunchCmdTextBox</tabstop>
<tabstop>postExitCmdTextBox</tabstop>
- <tabstop>settingsTabs</tabstop>
+ <tabstop>proxyDefaultBtn</tabstop>
+ <tabstop>proxyNoneBtn</tabstop>
+ <tabstop>proxySOCKS5Btn</tabstop>
+ <tabstop>proxyHTTPBtn</tabstop>
+ <tabstop>proxyAddrEdit</tabstop>
+ <tabstop>proxyPortEdit</tabstop>
+ <tabstop>proxyUserEdit</tabstop>
+ <tabstop>proxyPassEdit</tabstop>
+ <tabstop>jprofilerPathEdit</tabstop>
+ <tabstop>jprofilerPathBtn</tabstop>
+ <tabstop>jprofilerCheckBtn</tabstop>
+ <tabstop>jvisualvmPathEdit</tabstop>
+ <tabstop>jvisualvmPathBtn</tabstop>
+ <tabstop>jvisualvmCheckBtn</tabstop>
+ <tabstop>mceditPathEdit</tabstop>
+ <tabstop>mceditPathBtn</tabstop>
+ <tabstop>mceditCheckBtn</tabstop>
</tabstops>
<resources>
<include location="../../graphics.qrc"/>
diff --git a/gui/pages/InstanceSettingsPage.ui b/gui/pages/InstanceSettingsPage.ui
index b8af6c60..b141dbca 100644
--- a/gui/pages/InstanceSettingsPage.ui
+++ b/gui/pages/InstanceSettingsPage.ui
@@ -427,6 +427,30 @@
</item>
</layout>
</widget>
+ <tabstops>
+ <tabstop>settingsTabs</tabstop>
+ <tabstop>javaSettingsGroupBox</tabstop>
+ <tabstop>javaPathTextBox</tabstop>
+ <tabstop>javaDetectBtn</tabstop>
+ <tabstop>javaBrowseBtn</tabstop>
+ <tabstop>javaTestBtn</tabstop>
+ <tabstop>memoryGroupBox</tabstop>
+ <tabstop>minMemSpinBox</tabstop>
+ <tabstop>maxMemSpinBox</tabstop>
+ <tabstop>permGenSpinBox</tabstop>
+ <tabstop>javaArgumentsGroupBox</tabstop>
+ <tabstop>jvmArgsTextBox</tabstop>
+ <tabstop>windowSizeGroupBox</tabstop>
+ <tabstop>maximizedCheckBox</tabstop>
+ <tabstop>windowWidthSpinBox</tabstop>
+ <tabstop>windowHeightSpinBox</tabstop>
+ <tabstop>consoleSettingsBox</tabstop>
+ <tabstop>showConsoleCheck</tabstop>
+ <tabstop>autoCloseConsoleCheck</tabstop>
+ <tabstop>customCommandsGroupBox</tabstop>
+ <tabstop>preLaunchCmdTextBox</tabstop>
+ <tabstop>postExitCmdTextBox</tabstop>
+ </tabstops>
<resources/>
<connections/>
</ui>
diff --git a/logic/BaseVersionList.h b/logic/BaseVersionList.h
index f903b52c..21b44e8d 100644
--- a/logic/BaseVersionList.h
+++ b/logic/BaseVersionList.h
@@ -100,10 +100,7 @@ public:
/*!
* Sorts the version list.
*/
- #pragma clang diagnostic push
- #pragma clang diagnostic ignored "-Woverloaded-virtual"
virtual void sort() = 0;
- #pragma clang diagnostic pop
protected
slots:
diff --git a/logic/DefaultVariable.h b/logic/DefaultVariable.h
new file mode 100644
index 00000000..38d7ecc2
--- /dev/null
+++ b/logic/DefaultVariable.h
@@ -0,0 +1,35 @@
+#pragma once
+
+template <typename T>
+class DefaultVariable
+{
+public:
+ DefaultVariable(const T & value)
+ {
+ defaultValue = value;
+ }
+ DefaultVariable<T> & operator =(const T & value)
+ {
+ currentValue = value;
+ is_default = currentValue == defaultValue;
+ is_explicit = true;
+ return *this;
+ }
+ operator const T &() const
+ {
+ return is_default ? defaultValue : currentValue;
+ }
+ bool isDefault() const
+ {
+ return is_default;
+ }
+ bool isExplicit() const
+ {
+ return is_explicit;
+ }
+private:
+ T currentValue;
+ T defaultValue;
+ bool is_default = true;
+ bool is_explicit = false;
+};
diff --git a/logic/InstanceList.cpp b/logic/InstanceList.cpp
index 8a68c334..650f5c80 100644
--- a/logic/InstanceList.cpp
+++ b/logic/InstanceList.cpp
@@ -331,7 +331,29 @@ QSet<FTBRecord> InstanceList::discoverFTBInstances()
continue;
record.name = attrs.value("name").toString();
record.logo = attrs.value("logo").toString();
- record.mcVersion = attrs.value("mcVersion").toString();
+ auto customVersions = attrs.value("customMCVersions");
+ if(!customVersions.isNull())
+ {
+ QMap<QString, QString> versionMatcher;
+ QString customVersionsStr = customVersions.toString();
+ QStringList list = customVersionsStr.split(';');
+ for(auto item: list)
+ {
+ auto segment = item.split('^');
+ if(segment.size() != 2)
+ {
+ QLOG_ERROR() << "FTB: Segment of size < 2 in " << customVersionsStr;
+ continue;
+ }
+ versionMatcher[segment[0]] = segment[1];
+ }
+ auto actualVersion = attrs.value("version").toString();
+ record.mcVersion = versionMatcher[actualVersion];
+ }
+ else
+ {
+ record.mcVersion = attrs.value("mcVersion").toString();
+ }
record.description = attrs.value("description").toString();
records.insert(record);
}
diff --git a/logic/VersionFilterData.cpp b/logic/VersionFilterData.cpp
index e8523018..866d4947 100644
--- a/logic/VersionFilterData.cpp
+++ b/logic/VersionFilterData.cpp
@@ -65,4 +65,8 @@ VersionFilterData::VersionFilterData()
* (these versions need to be tested by us first)
*/
legacyCutoffDate = timeFromS3Time("2013-06-25T15:08:56+02:00");
+ lwjglWhitelist =
+ QSet<QString>{"net.java.jinput:jinput", "net.java.jinput:jinput-platform",
+ "net.java.jutils:jutils", "org.lwjgl.lwjgl:lwjgl",
+ "org.lwjgl.lwjgl:lwjgl_util", "org.lwjgl.lwjgl:lwjgl-platform"};
}
diff --git a/logic/VersionFilterData.h b/logic/VersionFilterData.h
index e010adc7..98ecb36c 100644
--- a/logic/VersionFilterData.h
+++ b/logic/VersionFilterData.h
@@ -22,5 +22,7 @@ struct VersionFilterData
QSet<QString> legacyBlacklist;
// no new versions below this date will be accepted from Mojang servers
QDateTime legacyCutoffDate;
+ // Libraries that belong to LWJGL
+ QSet<QString> lwjglWhitelist;
};
extern VersionFilterData g_VersionFilterData;
diff --git a/logic/forge/ForgeInstaller.cpp b/logic/forge/ForgeInstaller.cpp
index 7ab0a09b..74db2bfc 100644
--- a/logic/forge/ForgeInstaller.cpp
+++ b/logic/forge/ForgeInstaller.cpp
@@ -133,8 +133,8 @@ bool ForgeInstaller::add(OneSixInstance *to)
int sliding_insert_window = 0;
{
QJsonArray librariesPlus;
- // A blacklist - we ignore these entirely
- QSet<QString> blacklist{"lwjgl", "lwjgl_util", "lwjgl-platform"};
+ // A blacklist
+ QSet<QString> blacklist{"authlib", "realms"};
//
QList<QString> xzlist{"org.scala-lang", "com.typesafe"};
// for each library in the version we are adding (except for the blacklisted)
@@ -143,15 +143,38 @@ bool ForgeInstaller::add(OneSixInstance *to)
QString libName = lib->name();
QString rawName = lib->rawName();
- // ignore blacklisted stuff
+ // ignore lwjgl libraries.
+ if (g_VersionFilterData.lwjglWhitelist.contains(lib->fullname()))
+ continue;
+ // ignore other blacklisted (realms, authlib)
if (blacklist.contains(libName))
continue;
// WARNING: This could actually break.
// if this is the actual forge lib, set an absolute url for the download
- if (libName.contains("minecraftforge"))
+ if(m_forge_version->type == ForgeVersion::Gradle)
+ {
+ if (libName == "forge")
+ {
+ lib->m_name.setClassifier("universal");
+ lib->finalize();
+ }
+ else if (libName == "minecraftforge")
+ {
+ QString forgeCoord ("net.minecraftforge:forge:%1:universal");
+ // using insane form of the MC version...
+ QString longVersion = m_forge_version->mcver + "-" + m_forge_version->jobbuildver;
+ GradleSpecifier spec(forgeCoord.arg(longVersion));
+ lib->m_name = spec;
+ lib->finalize();
+ }
+ }
+ else
{
- lib->setAbsoluteUrl(m_universal_url);
+ if (libName.contains("minecraftforge"))
+ {
+ lib->setAbsoluteUrl(m_universal_url);
+ }
}
// WARNING: This could actually break.
@@ -192,7 +215,7 @@ bool ForgeInstaller::add(OneSixInstance *to)
{
// add lib
libObj.insert("insert", QString("prepend"));
- if (lib->name() == "minecraftforge")
+ if (lib->name() == "minecraftforge" || lib->name() == "forge")
{
libObj.insert("MMC-depend", QString("hard"));
}
diff --git a/logic/forge/ForgeVersion.h b/logic/forge/ForgeVersion.h
index 466f46bd..c7adc572 100644
--- a/logic/forge/ForgeVersion.h
+++ b/logic/forge/ForgeVersion.h
@@ -17,6 +17,13 @@ struct ForgeVersion : public BaseVersion
QString filename();
QString url();
+ enum
+ {
+ Invalid,
+ Legacy,
+ Gradle
+ } type = Invalid;
+
bool usesInstaller();
int m_buildnr = 0;
diff --git a/logic/forge/ForgeVersionList.cpp b/logic/forge/ForgeVersionList.cpp
index efb30ba6..ee7c63e3 100644
--- a/logic/forge/ForgeVersionList.cpp
+++ b/logic/forge/ForgeVersionList.cpp
@@ -286,6 +286,7 @@ bool ForgeListLoadTask::parseForgeList(QList<BaseVersionPtr> &out)
fVersion->installer_filename = installer_filename;
fVersion->universal_filename = universal_filename;
fVersion->m_buildnr = build_nr;
+ fVersion->type = ForgeVersion::Legacy;
out.append(fVersion);
}
}
@@ -335,6 +336,10 @@ bool ForgeListLoadTask::parseForgeGradleList(QList<BaseVersionPtr> &out)
QJsonObject number = it.value().toObject();
std::shared_ptr<ForgeVersion> fVersion(new ForgeVersion());
fVersion->m_buildnr = number.value("build").toDouble();
+ if(fVersion->m_buildnr >= 953 && fVersion->m_buildnr <= 965)
+ {
+ QLOG_DEBUG() << fVersion->m_buildnr;
+ }
fVersion->jobbuildver = number.value("version").toString();
fVersion->branch = number.value("branch").toString("");
fVersion->mcver = number.value("mcversion").toString();
@@ -395,6 +400,7 @@ bool ForgeListLoadTask::parseForgeGradleList(QList<BaseVersionPtr> &out)
}
fVersion->universal_filename = universal_filename;
fVersion->installer_filename = installer_filename;
+ fVersion->type = ForgeVersion::Gradle;
out.append(fVersion);
}
return true;
diff --git a/logic/liteloader/LiteLoaderVersionList.cpp b/logic/liteloader/LiteLoaderVersionList.cpp
index eced78e9..af8509d6 100644
--- a/logic/liteloader/LiteLoaderVersionList.cpp
+++ b/logic/liteloader/LiteLoaderVersionList.cpp
@@ -212,7 +212,7 @@ void LLListLoadTask::listDownloaded()
{
auto lib = RawLibrary::fromJson(libobject, "versions.json");
// hack to make liteloader 1.7.10_00 work
- if(lib->m_name == "org.ow2.asm:asm-all:5.0.3")
+ if(lib->m_name == GradleSpecifier("org.ow2.asm:asm-all:5.0.3"))
{
lib->m_base_url = "http://repo.maven.apache.org/maven2/";
}
diff --git a/logic/minecraft/GradleSpecifier.h b/logic/minecraft/GradleSpecifier.h
new file mode 100644
index 00000000..8a02e4d9
--- /dev/null
+++ b/logic/minecraft/GradleSpecifier.h
@@ -0,0 +1,129 @@
+#pragma once
+
+#include <QString>
+#include <QStringList>
+#include "logic/DefaultVariable.h"
+
+struct GradleSpecifier
+{
+ GradleSpecifier()
+ {
+ m_valid = false;
+ }
+ GradleSpecifier(QString value)
+ {
+ operator=(value);
+ }
+ GradleSpecifier & operator =(const QString & value)
+ {
+ /*
+ org.gradle.test.classifiers : service : 1.0 : jdk15 @ jar
+ DEBUG 0 "org.gradle.test.classifiers:service:1.0:jdk15@jar"
+ DEBUG 1 "org.gradle.test.classifiers"
+ DEBUG 2 "service"
+ DEBUG 3 "1.0"
+ DEBUG 4 ":jdk15"
+ DEBUG 5 "jdk15"
+ DEBUG 6 "@jar"
+ DEBUG 7 "jar"
+ */
+ QRegExp matcher("([^:@]+):([^:@]+):([^:@]+)" "(:([^:@]+))?" "(@([^:@]+))?");
+ m_valid = matcher.exactMatch(value);
+ auto elements = matcher.capturedTexts();
+ m_groupId = elements[1];
+ m_artifactId = elements[2];
+ m_version = elements[3];
+ m_classifier = elements[5];
+ if(!elements[7].isEmpty())
+ {
+ m_extension = elements[7];
+ }
+ return *this;
+ }
+ operator QString() const
+ {
+ if(!m_valid)
+ return "INVALID";
+ QString retval = m_groupId + ":" + m_artifactId + ":" + m_version;
+ if(!m_classifier.isEmpty())
+ {
+ retval += ":" + m_classifier;
+ }
+ if(m_extension.isExplicit())
+ {
+ retval += "@" + m_extension;
+ }
+ return retval;
+ }
+ QString toPath() const
+ {
+ if(!m_valid)
+ return "INVALID";
+ QString path = m_groupId;
+ path.replace('.', '/');
+ path += '/' + m_artifactId + '/' + m_version + '/' + m_artifactId + '-' + m_version;
+ if(!m_classifier.isEmpty())
+ {
+ path += "-" + m_classifier;
+ }
+ path += "." + m_extension;
+ return path;
+ }
+ inline bool valid() const
+ {
+ return m_valid;
+ }
+ inline QString version() const
+ {
+ return m_version;
+ }
+ inline QString groupId() const
+ {
+ return m_groupId;
+ }
+ inline QString artifactId() const
+ {
+ return m_artifactId;
+ }
+ inline void setClassifier(const QString & classifier)
+ {
+ m_classifier = classifier;
+ }
+ inline QString classifier() const
+ {
+ return m_classifier;
+ }
+ inline QString extension() const
+ {
+ return m_extension;
+ }
+ inline QString artifactPrefix() const
+ {
+ return m_groupId + ":" + m_artifactId;
+ }
+ bool matchName(const GradleSpecifier & other)
+ {
+ return other.artifactId() == artifactId() && other.groupId() == groupId();
+ }
+ bool operator==(const GradleSpecifier & other)
+ {
+ if(m_groupId != other.m_groupId)
+ return false;
+ if(m_artifactId != other.m_artifactId)
+ return false;
+ if(m_version != other.m_version)
+ return false;
+ if(m_classifier != other.m_classifier)
+ return false;
+ if(m_extension != other.m_extension)
+ return false;
+ return true;
+ }
+private:
+ QString m_groupId;
+ QString m_artifactId;
+ QString m_version;
+ QString m_classifier;
+ DefaultVariable<QString> m_extension = DefaultVariable<QString>("jar");
+ bool m_valid = false;
+};
diff --git a/logic/minecraft/MinecraftVersion.cpp b/logic/minecraft/MinecraftVersion.cpp
index 488a180a..8368c430 100644
--- a/logic/minecraft/MinecraftVersion.cpp
+++ b/logic/minecraft/MinecraftVersion.cpp
@@ -2,6 +2,8 @@
#include "InstanceVersion.h"
#include "VersionBuildError.h"
#include "VersionBuilder.h"
+#include "MultiMC.h"
+#include "logic/settings/SettingsObject.h"
bool MinecraftVersion::usesLegacyLauncher()
{
@@ -141,3 +143,15 @@ QString MinecraftVersion::getPatchFilename()
{
return QString();
}
+
+bool MinecraftVersion::needsUpdate()
+{
+ auto settings = MMC->settings();
+ bool result = hasUpdate() && settings->get("AutoUpdateMinecraftVersions").toBool();
+ return result;
+}
+
+bool MinecraftVersion::hasUpdate()
+{
+ return m_versionSource == Remote || (m_versionSource == Local && upstreamUpdate);
+}
diff --git a/logic/minecraft/MinecraftVersion.h b/logic/minecraft/MinecraftVersion.h
index 82073a97..e06dadb1 100644
--- a/logic/minecraft/MinecraftVersion.h
+++ b/logic/minecraft/MinecraftVersion.h
@@ -45,14 +45,8 @@ public: /* methods */
virtual QString getPatchVersion() override;
virtual QString getPatchName() override;
virtual QString getPatchFilename() override;
- bool needsUpdate()
- {
- return m_versionSource == Remote;
- }
- bool hasUpdate()
- {
- return m_versionSource == Remote || (m_versionSource == Local && upstreamUpdate);
- }
+ bool needsUpdate();
+ bool hasUpdate();
private: /* methods */
void applyFileTo(InstanceVersion *version);
diff --git a/logic/minecraft/MinecraftVersionList.cpp b/logic/minecraft/MinecraftVersionList.cpp
index 3aa1ac01..ee228528 100644
--- a/logic/minecraft/MinecraftVersionList.cpp
+++ b/logic/minecraft/MinecraftVersionList.cpp
@@ -266,7 +266,8 @@ void MinecraftVersionList::loadMojangList(QJsonDocument jsonDoc, VersionSource s
QString versionTypeStr = versionObj.value("type").toString("");
if (versionTypeStr.isEmpty())
{
- // FIXME: log this somewhere
+ QLOG_ERROR() << "Ignoring" << versionID
+ << "because it doesn't have the version type set.";
continue;
}
// OneSix or Legacy. use filter to determine type
@@ -284,10 +285,13 @@ void MinecraftVersionList::loadMojangList(QJsonDocument jsonDoc, VersionSource s
}
else
{
- // FIXME: log this somewhere
+ QLOG_ERROR() << "Ignoring" << versionID
+ << "because it has an invalid version type.";
continue;
}
mcVersion->m_type = versionTypeStr;
+ QLOG_INFO() << "Loaded version" << versionID << "from"
+ << ((source == Remote) ? "remote" : "local") << "version list.";
tempList.append(mcVersion);
}
updateListData(tempList);
@@ -333,12 +337,6 @@ void MinecraftVersionList::updateListData(QList<BaseVersionPtr> versions)
{
continue;
}
- // is it actually an update?
- if (orig->m_updateTime >= added->m_updateTime)
- {
- // nope.
- continue;
- }
// alright, it's an update. put it inside the original, for further processing.
orig->upstreamUpdate = added;
}
@@ -451,13 +449,10 @@ void MCVListVersionUpdateTask::json_downloaded()
}
QList<RawLibraryPtr> filteredLibs;
QList<RawLibraryPtr> lwjglLibs;
- QSet<QString> lwjglFilter = {
- "net.java.jinput:jinput", "net.java.jinput:jinput-platform",
- "net.java.jutils:jutils", "org.lwjgl.lwjgl:lwjgl",
- "org.lwjgl.lwjgl:lwjgl_util", "org.lwjgl.lwjgl:lwjgl-platform"};
+
for (auto lib : file->overwriteLibs)
{
- if (lwjglFilter.contains(lib->fullname()))
+ if (g_VersionFilterData.lwjglWhitelist.contains(lib->fullname()))
{
lwjglLibs.append(lib);
}
@@ -581,9 +576,11 @@ void MinecraftVersionList::finalizeUpdate(QString version)
auto updatedVersion = std::dynamic_pointer_cast<MinecraftVersion>(m_vlist[idx]);
+ // reject any updates to builtin versions.
if (updatedVersion->m_versionSource == Builtin)
return;
+ // if we have an update for the version, replace it, make the update local
if (updatedVersion->upstreamUpdate)
{
auto updatedWith = updatedVersion->upstreamUpdate;
@@ -593,6 +590,7 @@ void MinecraftVersionList::finalizeUpdate(QString version)
}
else
{
+ // otherwise, just set the version as local;
updatedVersion->m_versionSource = Local;
}
diff --git a/logic/minecraft/OneSixLibrary.cpp b/logic/minecraft/OneSixLibrary.cpp
index 7f69d9f8..c562f353 100644
--- a/logic/minecraft/OneSixLibrary.cpp
+++ b/logic/minecraft/OneSixLibrary.cpp
@@ -30,7 +30,7 @@ OneSixLibrary::OneSixLibrary(RawLibraryPtr base)
m_hint = base->m_hint;
m_absolute_url = base->m_absolute_url;
extract_excludes = base->extract_excludes;
- m_native_suffixes = base->m_native_suffixes;
+ m_native_classifiers = base->m_native_classifiers;
m_rules = base->m_rules;
finalize();
}
@@ -42,31 +42,8 @@ OneSixLibraryPtr OneSixLibrary::fromRawLibrary(RawLibraryPtr lib)
void OneSixLibrary::finalize()
{
- QStringList parts = m_name.split(':');
- QString relative = parts[0];
- relative.replace('.', '/');
- relative += '/' + parts[1] + '/' + parts[2] + '/' + parts[1] + '-' + parts[2];
-
- if (!isNative())
- relative += ".jar";
- else
- {
- if (m_native_suffixes.contains(currentSystem))
- {
- relative += "-" + m_native_suffixes[currentSystem] + ".jar";
- }
- else
- {
- // really, bad.
- relative += ".jar";
- }
- }
-
- m_decentname = parts[1];
- m_decentversion = minVersion = parts[2];
- m_storage_path = relative;
- m_download_url = m_base_url + relative;
-
+ QString relative;
+
if (m_rules.empty())
{
m_is_active = true;
@@ -84,13 +61,32 @@ void OneSixLibrary::finalize()
}
if (isNative())
{
- m_is_active = m_is_active && m_native_suffixes.contains(currentSystem);
+ GradleSpecifier nativeSpec = m_name;
+ m_is_active = m_is_active && m_native_classifiers.contains(currentSystem);
m_decenttype = "Native";
+ if(m_native_classifiers.contains(currentSystem))
+ {
+ nativeSpec.setClassifier(m_native_classifiers[currentSystem]);
+ }
+ else
+ {
+ nativeSpec.setClassifier("INVALID");
+ }
+ relative = nativeSpec.toPath();
}
else
{
+ relative = m_name.toPath();
m_decenttype = "Java";
}
+
+ m_decentname = m_name.artifactId();
+ m_decentversion = minVersion = m_name.version();
+ m_storage_path = relative;
+ if(m_base_url.isEmpty())
+ m_download_url = QString("https://" + URLConstants::LIBRARY_BASE) + relative;
+ else
+ m_download_url = m_base_url + relative;
}
void OneSixLibrary::setName(const QString &name)
@@ -103,11 +99,11 @@ void OneSixLibrary::setBaseUrl(const QString &base_url)
}
void OneSixLibrary::addNative(OpSys os, const QString &suffix)
{
- m_native_suffixes[os] = suffix;
+ m_native_classifiers[os] = suffix;
}
void OneSixLibrary::clearSuffixes()
{
- m_native_suffixes.clear();
+ m_native_classifiers.clear();
}
void OneSixLibrary::setRules(QList<std::shared_ptr<Rule>> rules)
{
diff --git a/logic/minecraft/RawLibrary.cpp b/logic/minecraft/RawLibrary.cpp
index 7e0ebff0..76bd7260 100644
--- a/logic/minecraft/RawLibrary.cpp
+++ b/logic/minecraft/RawLibrary.cpp
@@ -13,20 +13,20 @@ RawLibraryPtr RawLibrary::fromJson(const QJsonObject &libObj, const QString &fil
}
out->m_name = libObj.value("name").toString();
- auto readString = [libObj, filename](const QString & key, QString & variable)
+ auto readString = [libObj, filename](const QString & key, QString & variable) -> bool
{
- if (libObj.contains(key))
+ if (!libObj.contains(key))
+ return false;
+ QJsonValue val = libObj.value(key);
+
+ if (!val.isString())
{
- QJsonValue val = libObj.value(key);
- if (!val.isString())
- {
- QLOG_WARN() << key << "is not a string in" << filename << "(skipping)";
- }
- else
- {
- variable = val.toString();
- }
+ QLOG_WARN() << key << "is not a string in" << filename << "(skipping)";
+ return false;
}
+
+ variable = val.toString();
+ return true;
};
readString("url", out->m_base_url);
@@ -54,7 +54,7 @@ RawLibraryPtr RawLibrary::fromJson(const QJsonObject &libObj, const QString &fil
OpSys opSys = OpSys_fromString(it.key());
if (opSys != Os_Other)
{
- out->m_native_suffixes[opSys] = it.value().toString();
+ out->m_native_classifiers[opSys] = it.value().toString();
}
}
}
@@ -134,13 +134,13 @@ RawLibraryPtr RawLibrary::fromJsonPlus(const QJsonObject &libObj, const QString
bool RawLibrary::isNative() const
{
- return m_native_suffixes.size() != 0;
+ return m_native_classifiers.size() != 0;
}
QJsonObject RawLibrary::toJson()
{
QJsonObject libRoot;
- libRoot.insert("name", m_name);
+ libRoot.insert("name", (QString)m_name);
if (m_absolute_url.size())
libRoot.insert("MMC-absoluteUrl", m_absolute_url);
if (m_hint.size())
@@ -154,8 +154,8 @@ QJsonObject RawLibrary::toJson()
if (isNative())
{
QJsonObject nativeList;
- auto iter = m_native_suffixes.begin();
- while (iter != m_native_suffixes.end())
+ auto iter = m_native_classifiers.begin();
+ while (iter != m_native_classifiers.end())
{
nativeList.insert(OpSys_toString(iter.key()), iter.value());
iter++;
@@ -188,18 +188,5 @@ QJsonObject RawLibrary::toJson()
QString RawLibrary::fullname()
{
- QStringList parts = m_name.split(':');
- return parts[0] + ":" + parts[1];
-}
-
-QString RawLibrary::group()
-{
- QStringList parts = m_name.split(':');
- return parts[0];
-}
-
-QString RawLibrary::version()
-{
- QStringList parts = m_name.split(':');
- return parts[2];
+ return m_name.artifactPrefix();
}
diff --git a/logic/minecraft/RawLibrary.h b/logic/minecraft/RawLibrary.h
index f5a28c61..6e8f7f10 100644
--- a/logic/minecraft/RawLibrary.h
+++ b/logic/minecraft/RawLibrary.h
@@ -8,6 +8,7 @@
#include "logic/minecraft/OneSixRule.h"
#include "logic/minecraft/OpSys.h"
+#include "GradleSpecifier.h"
#include "logic/net/URLConstants.h"
class RawLibrary;
@@ -23,15 +24,14 @@ public: /* methods */
QJsonObject toJson();
QString fullname();
- QString version();
- QString group();
public: /* data */
- QString m_name;
- QString m_base_url = "https://" + URLConstants::LIBRARY_BASE;
+ GradleSpecifier m_name;
+ QString m_base_url;
+
/// type hint - modifies how the library is treated
QString m_hint;
- /// absolute URL. takes precedence over m_download_path, if defined
+ /// DEPRECATED: absolute URL. takes precedence over m_download_path, if defined
QString m_absolute_url;
bool applyExcludes = false;
@@ -40,7 +40,7 @@ public: /* data */
/// Returns true if the library is native
bool isNative() const;
/// native suffixes per OS
- QMap<OpSys, QString> m_native_suffixes;
+ QMap<OpSys, QString> m_native_classifiers;
bool applyRules = false;
QList<std::shared_ptr<Rule>> m_rules;
diff --git a/logic/minecraft/VersionFile.cpp b/logic/minecraft/VersionFile.cpp
index 93f57116..600c71ae 100644
--- a/logic/minecraft/VersionFile.cpp
+++ b/logic/minecraft/VersionFile.cpp
@@ -17,13 +17,13 @@ using namespace MMCJson;
#define CURRENT_MINIMUM_LAUNCHER_VERSION 14
-int findLibrary(QList<OneSixLibraryPtr> haystack, const QString &needle)
+int findLibraryByName(QList<OneSixLibraryPtr> haystack, const GradleSpecifier &needle)
{
int retval = -1;
for (int i = 0; i < haystack.size(); ++i)
{
- QString chunk = haystack.at(i)->rawName();
- if (QRegExp(needle, Qt::CaseSensitive, QRegExp::WildcardUnix).indexIn(chunk) != -1)
+
+ if(haystack.at(i)->m_name.matchName(needle))
{
// only one is allowed.
if (retval != -1)
@@ -382,7 +382,7 @@ void VersionFile::applyTo(InstanceVersion *version)
case RawLibrary::Apply:
{
// QLOG_INFO() << "Applying lib " << lib->name;
- int index = findLibrary(version->libraries, lib->m_name);
+ int index = findLibraryByName(version->libraries, lib->m_name);
if (index >= 0)
{
auto library = version->libraries[index];
@@ -405,7 +405,7 @@ void VersionFile::applyTo(InstanceVersion *version)
if (lib->isNative())
{
// library->clearSuffixes();
- library->m_native_suffixes = lib->m_native_suffixes;
+ library->m_native_classifiers = lib->m_native_classifiers;
/*
for (auto native : lib->natives)
{
@@ -429,9 +429,7 @@ void VersionFile::applyTo(InstanceVersion *version)
case RawLibrary::Prepend:
{
// QLOG_INFO() << "Adding lib " << lib->name;
- const int startOfVersion = lib->m_name.lastIndexOf(':') + 1;
- const int index = findLibrary(
- version->libraries, QString(lib->m_name).replace(startOfVersion, INT_MAX, '*'));
+ const int index = findLibraryByName(version->libraries, lib->m_name);
if (index < 0)
{
if (lib->insertType == RawLibrary::Append)
@@ -446,8 +444,8 @@ void VersionFile::applyTo(InstanceVersion *version)
else
{
auto otherLib = version->libraries.at(index);
- const Util::Version ourVersion = lib->m_name.mid(startOfVersion, INT_MAX);
- const Util::Version otherVersion = otherLib->version();
+ const Util::Version ourVersion = lib->m_name.version();
+ const Util::Version otherVersion = otherLib->m_name.version();
// if the existing version is a hard dependency we can either use it or
// fail, but we can't change it
if (otherLib->dependType == OneSixLibrary::Hard)
@@ -497,16 +495,17 @@ void VersionFile::applyTo(InstanceVersion *version)
}
case RawLibrary::Replace:
{
- QString toReplace;
+ GradleSpecifier toReplace;
if (lib->insertData.isEmpty())
{
- const int startOfVersion = lib->m_name.lastIndexOf(':') + 1;
- toReplace = QString(lib->m_name).replace(startOfVersion, INT_MAX, '*');
+ toReplace = lib->m_name;
}
else
+ {
toReplace = lib->insertData;
+ }
// QLOG_INFO() << "Replacing lib " << toReplace << " with " << lib->name;
- int index = findLibrary(version->libraries, toReplace);
+ int index = findLibraryByName(version->libraries, toReplace);
if (index >= 0)
{
version->libraries.replace(index, OneSixLibrary::fromRawLibrary(lib));
@@ -521,7 +520,7 @@ void VersionFile::applyTo(InstanceVersion *version)
}
for (auto lib : removeLibs)
{
- int index = findLibrary(version->libraries, lib);
+ int index = findLibraryByName(version->libraries, lib);
if (index >= 0)
{
// QLOG_INFO() << "Removing lib " << lib;
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 3b2b8b74..d56988e0 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -22,6 +22,7 @@ endmacro()
# Tests START #
add_unit_test(pathutils tst_pathutils.cpp)
+add_unit_test(gradlespecifier tst_gradlespecifier.cpp)
add_unit_test(userutils tst_userutils.cpp)
add_unit_test(inifile tst_inifile.cpp)
add_unit_test(UpdateChecker tst_UpdateChecker.cpp)
diff --git a/tests/tst_gradlespecifier.cpp b/tests/tst_gradlespecifier.cpp
new file mode 100644
index 00000000..69dd54f7
--- /dev/null
+++ b/tests/tst_gradlespecifier.cpp
@@ -0,0 +1,77 @@
+#include <QTest>
+#include "TestUtil.h"
+
+#include "logic/minecraft/GradleSpecifier.h"
+
+class GradleSpecifierTest : public QObject
+{
+ Q_OBJECT
+private
+slots:
+ void initTestCase()
+ {
+
+ }
+ void cleanupTestCase()
+ {
+
+ }
+
+ void test_Positive_data()
+ {
+ QTest::addColumn<QString>("through");
+
+ QTest::newRow("3 parter") << "org.gradle.test.classifiers:service:1.0";
+ QTest::newRow("classifier") << "org.gradle.test.classifiers:service:1.0:jdk15";
+ QTest::newRow("jarextension") << "org.gradle.test.classifiers:service:1.0@jar";
+ QTest::newRow("jarboth") << "org.gradle.test.classifiers:service:1.0:jdk15@jar";
+ QTest::newRow("packxz") << "org.gradle.test.classifiers:service:1.0:jdk15@jar.pack.xz";
+ }
+ void test_Positive()
+ {
+ QFETCH(QString, through);
+
+ QString converted = GradleSpecifier(through);
+
+ QCOMPARE(converted, through);
+ }
+
+ void test_Path_data()
+ {
+ QTest::addColumn<QString>("spec");
+ QTest::addColumn<QString>("expected");
+
+ QTest::newRow("3 parter") << "group.id:artifact:1.0" << "group/id/artifact/1.0/artifact-1.0.jar";
+ QTest::newRow("doom") << "id.software:doom:1.666:demons@wad" << "id/software/doom/1.666/doom-1.666-demons.wad";
+ }
+ void test_Path()
+ {
+ QFETCH(QString, spec);
+ QFETCH(QString, expected);
+
+ QString converted = GradleSpecifier(spec).toPath();
+
+ QCOMPARE(converted, expected);
+ }
+ void test_Negative_data()
+ {
+ QTest::addColumn<QString>("input");
+
+ QTest::newRow("too many :") << "org:gradle.test:class:::ifiers:service:1.0::";
+ QTest::newRow("nonsense") << "I like turtles";
+ QTest::newRow("empty string") << "";
+ QTest::newRow("missing version") << "herp.derp:artifact";
+ }
+ void test_Negative()
+ {
+ QFETCH(QString, input);
+
+ GradleSpecifier spec(input);
+ QVERIFY(!spec.valid());
+ QCOMPARE(spec.operator QString(), QString("INVALID"));
+ }
+};
+
+QTEST_GUILESS_MAIN_MULTIMC(GradleSpecifierTest)
+
+#include "tst_gradlespecifier.moc"