diff options
author | Petr Mrázek <peterix@gmail.com> | 2014-12-18 02:48:14 +0100 |
---|---|---|
committer | Petr Mrázek <peterix@gmail.com> | 2014-12-27 20:50:33 +0100 |
commit | a30a9559c749446165ec84e737fe85b44a462584 (patch) | |
tree | 9e6bfadfc4e10f01ab2580c33e2c682d57b4ce99 /logic | |
parent | 01f44e0f39a808d3d5285c394d83a8fc80421890 (diff) | |
download | MultiMC-a30a9559c749446165ec84e737fe85b44a462584.tar MultiMC-a30a9559c749446165ec84e737fe85b44a462584.tar.gz MultiMC-a30a9559c749446165ec84e737fe85b44a462584.tar.lz MultiMC-a30a9559c749446165ec84e737fe85b44a462584.tar.xz MultiMC-a30a9559c749446165ec84e737fe85b44a462584.zip |
NOISSUE Fix jar mods for OnesSix
Diffstat (limited to 'logic')
-rw-r--r-- | logic/BaseInstance.cpp | 183 | ||||
-rw-r--r-- | logic/BaseInstance.h | 37 | ||||
-rw-r--r-- | logic/BaseInstance_p.h | 36 | ||||
-rw-r--r-- | logic/InstanceFactory.cpp | 3 | ||||
-rw-r--r-- | logic/InstanceLauncher.cpp | 94 | ||||
-rw-r--r-- | logic/InstanceLauncher.h | 44 | ||||
-rw-r--r-- | logic/JarUtils.cpp | 161 | ||||
-rw-r--r-- | logic/JarUtils.h | 18 | ||||
-rw-r--r-- | logic/LegacyInstance.cpp | 109 | ||||
-rw-r--r-- | logic/LegacyInstance.h | 30 | ||||
-rw-r--r-- | logic/LegacyInstance_p.h | 32 | ||||
-rw-r--r-- | logic/LegacyUpdate.cpp | 160 | ||||
-rw-r--r-- | logic/LegacyUpdate.h | 9 | ||||
-rw-r--r-- | logic/ModList.h | 5 | ||||
-rw-r--r-- | logic/OneSixFTBInstance.cpp | 1 | ||||
-rw-r--r-- | logic/OneSixInstance.cpp | 97 | ||||
-rw-r--r-- | logic/OneSixInstance.h | 23 | ||||
-rw-r--r-- | logic/OneSixInstance_p.h | 33 | ||||
-rw-r--r-- | logic/OneSixUpdate.cpp | 121 | ||||
-rw-r--r-- | logic/OneSixUpdate.h | 4 | ||||
-rw-r--r-- | logic/URNResolver.cpp | 98 | ||||
-rw-r--r-- | logic/URNResolver.h | 18 | ||||
-rw-r--r-- | logic/minecraft/VersionFile.cpp | 1 |
23 files changed, 436 insertions, 881 deletions
diff --git a/logic/BaseInstance.cpp b/logic/BaseInstance.cpp index 1dc5b671..b23dde73 100644 --- a/logic/BaseInstance.cpp +++ b/logic/BaseInstance.cpp @@ -15,7 +15,6 @@ #include "MultiMC.h" #include "BaseInstance.h" -#include "BaseInstance_p.h" #include <QFileInfo> #include <QDir> @@ -31,61 +30,50 @@ #include "logic/icons/IconList.h" #include "logic/InstanceList.h" -BaseInstance::BaseInstance(BaseInstancePrivate *d_in, const QString &rootDir, - SettingsObject *settings_obj, QObject *parent) - : QObject(parent), inst_d(d_in) +BaseInstance::BaseInstance(const QString &rootDir, SettingsObject *settings, QObject *parent) + : QObject(parent) { - I_D(BaseInstance); - d->m_settings = std::shared_ptr<SettingsObject>(settings_obj); - d->m_rootDir = rootDir; - settings().registerSetting("name", "Unnamed Instance"); - settings().registerSetting("iconKey", "default"); + m_settings = std::shared_ptr<SettingsObject>(settings); + m_rootDir = rootDir; + + m_settings->registerSetting("name", "Unnamed Instance"); + m_settings->registerSetting("iconKey", "default"); connect(MMC->icons().get(), SIGNAL(iconUpdated(QString)), SLOT(iconUpdated(QString))); - settings().registerSetting("notes", ""); - settings().registerSetting("lastLaunchTime", 0); - - /* - * custom base jar has no default. it is determined in code... see the accessor methods for - *it - * - * for instances that DO NOT have the CustomBaseJar setting (legacy instances), - * [.]minecraft/bin/mcbackup.jar is the default base jar - */ - settings().registerSetting("UseCustomBaseJar", true); - settings().registerSetting("CustomBaseJar", ""); + m_settings->registerSetting("notes", ""); + m_settings->registerSetting("lastLaunchTime", 0); auto globalSettings = MMC->settings(); // Java Settings - settings().registerSetting("OverrideJava", false); - settings().registerSetting("OverrideJavaLocation", false); - settings().registerSetting("OverrideJavaArgs", false); - settings().registerOverride(globalSettings->getSetting("JavaPath")); - settings().registerOverride(globalSettings->getSetting("JvmArgs")); + 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 - settings().registerSetting({"OverrideCommands","OverrideLaunchCmd"}, false); - settings().registerOverride(globalSettings->getSetting("PreLaunchCommand")); - settings().registerOverride(globalSettings->getSetting("PostExitCommand")); + m_settings->registerSetting({"OverrideCommands","OverrideLaunchCmd"}, false); + m_settings->registerOverride(globalSettings->getSetting("PreLaunchCommand")); + m_settings->registerOverride(globalSettings->getSetting("PostExitCommand")); // Window Size - settings().registerSetting("OverrideWindow", false); - settings().registerOverride(globalSettings->getSetting("LaunchMaximized")); - settings().registerOverride(globalSettings->getSetting("MinecraftWinWidth")); - settings().registerOverride(globalSettings->getSetting("MinecraftWinHeight")); + m_settings->registerSetting("OverrideWindow", false); + m_settings->registerOverride(globalSettings->getSetting("LaunchMaximized")); + m_settings->registerOverride(globalSettings->getSetting("MinecraftWinWidth")); + m_settings->registerOverride(globalSettings->getSetting("MinecraftWinHeight")); // Memory - settings().registerSetting("OverrideMemory", false); - settings().registerOverride(globalSettings->getSetting("MinMemAlloc")); - settings().registerOverride(globalSettings->getSetting("MaxMemAlloc")); - settings().registerOverride(globalSettings->getSetting("PermGen")); + m_settings->registerSetting("OverrideMemory", false); + m_settings->registerOverride(globalSettings->getSetting("MinMemAlloc")); + m_settings->registerOverride(globalSettings->getSetting("MaxMemAlloc")); + m_settings->registerOverride(globalSettings->getSetting("PermGen")); // Console - settings().registerSetting("OverrideConsole", false); - settings().registerOverride(globalSettings->getSetting("ShowConsole")); - settings().registerOverride(globalSettings->getSetting("AutoCloseConsole")); - settings().registerOverride(globalSettings->getSetting("LogPrePostOutput")); + m_settings->registerSetting("OverrideConsole", false); + m_settings->registerOverride(globalSettings->getSetting("ShowConsole")); + m_settings->registerOverride(globalSettings->getSetting("AutoCloseConsole")); + m_settings->registerOverride(globalSettings->getSetting("LogPrePostOutput")); } void BaseInstance::iconUpdated(QString key) @@ -109,26 +97,22 @@ QString BaseInstance::id() const bool BaseInstance::isRunning() const { - I_D(BaseInstance); - return d->m_isRunning; + return m_isRunning; } -void BaseInstance::setRunning(bool running) const +void BaseInstance::setRunning(bool running) { - I_D(BaseInstance); - d->m_isRunning = running; + m_isRunning = running; } QString BaseInstance::instanceType() const { - I_D(BaseInstance); - return d->m_settings->get("InstanceType").toString(); + return m_settings->get("InstanceType").toString(); } QString BaseInstance::instanceRoot() const { - I_D(BaseInstance); - return d->m_rootDir; + return m_rootDir; } QString BaseInstance::minecraftRoot() const @@ -159,36 +143,34 @@ std::shared_ptr<BaseVersionList> BaseInstance::versionList() const SettingsObject &BaseInstance::settings() const { - I_D(BaseInstance); - return *d->m_settings; + return *m_settings; } BaseInstance::InstanceFlags BaseInstance::flags() const { - I_D(const BaseInstance); - return d->m_flags; + return m_flags; } + void BaseInstance::setFlags(const InstanceFlags &flags) { - I_D(BaseInstance); - if (flags != d->m_flags) + if (flags != m_flags) { - d->m_flags = flags; + m_flags = flags; emit flagsChanged(); emit propertiesChanged(this); } } + void BaseInstance::setFlag(const BaseInstance::InstanceFlag flag) { - I_D(BaseInstance); - d->m_flags |= flag; + m_flags |= flag; emit flagsChanged(); emit propertiesChanged(this); } + void BaseInstance::unsetFlag(const BaseInstance::InstanceFlag flag) { - I_D(BaseInstance); - d->m_flags &= ~flag; + m_flags &= ~flag; emit flagsChanged(); emit propertiesChanged(this); } @@ -200,69 +182,23 @@ bool BaseInstance::canLaunch() const bool BaseInstance::reload() { - return settings().reload(); -} - -QString BaseInstance::baseJar() const -{ - I_D(BaseInstance); - bool customJar = d->m_settings->get("UseCustomBaseJar").toBool(); - if (customJar) - { - return customBaseJar(); - } - else - return defaultBaseJar(); -} - -QString BaseInstance::customBaseJar() const -{ - I_D(BaseInstance); - QString value = d->m_settings->get("CustomBaseJar").toString(); - if (value.isNull() || value.isEmpty()) - { - return defaultCustomBaseJar(); - } - return value; -} - -void BaseInstance::setCustomBaseJar(QString val) -{ - I_D(BaseInstance); - if (val.isNull() || val.isEmpty() || val == defaultCustomBaseJar()) - d->m_settings->reset("CustomBaseJar"); - else - d->m_settings->set("CustomBaseJar", val); -} - -void BaseInstance::setShouldUseCustomBaseJar(bool val) -{ - I_D(BaseInstance); - d->m_settings->set("UseCustomBaseJar", val); -} - -bool BaseInstance::shouldUseCustomBaseJar() const -{ - I_D(BaseInstance); - return d->m_settings->get("UseCustomBaseJar").toBool(); + return m_settings->reload(); } qint64 BaseInstance::lastLaunch() const { - I_D(BaseInstance); - return d->m_settings->get("lastLaunchTime").value<qint64>(); + return m_settings->get("lastLaunchTime").value<qint64>(); } + void BaseInstance::setLastLaunch(qint64 val) { - I_D(BaseInstance); - d->m_settings->set("lastLaunchTime", val); + m_settings->set("lastLaunchTime", val); emit propertiesChanged(this); } void BaseInstance::setGroupInitial(QString val) { - I_D(BaseInstance); - d->m_group = val; + m_group = val; emit propertiesChanged(this); } @@ -274,44 +210,39 @@ void BaseInstance::setGroupPost(QString val) QString BaseInstance::group() const { - I_D(BaseInstance); - return d->m_group; + return m_group; } void BaseInstance::setNotes(QString val) { - I_D(BaseInstance); - d->m_settings->set("notes", val); + m_settings->set("notes", val); } + QString BaseInstance::notes() const { - I_D(BaseInstance); - return d->m_settings->get("notes").toString(); + return m_settings->get("notes").toString(); } void BaseInstance::setIconKey(QString val) { - I_D(BaseInstance); - d->m_settings->set("iconKey", val); + m_settings->set("iconKey", val); emit propertiesChanged(this); } + QString BaseInstance::iconKey() const { - I_D(BaseInstance); - return d->m_settings->get("iconKey").toString(); + return m_settings->get("iconKey").toString(); } void BaseInstance::setName(QString val) { - I_D(BaseInstance); - d->m_settings->set("name", val); + m_settings->set("name", val); emit propertiesChanged(this); } QString BaseInstance::name() const { - I_D(BaseInstance); - return d->m_settings->get("name").toString(); + return m_settings->get("name").toString(); } QString BaseInstance::windowTitle() const diff --git a/logic/BaseInstance.h b/logic/BaseInstance.h index c8517298..a0ac3c57 100644 --- a/logic/BaseInstance.h +++ b/logic/BaseInstance.h @@ -51,8 +51,7 @@ class BaseInstance : public QObject Q_OBJECT protected: /// no-touchy! - BaseInstance(BaseInstancePrivate *d, const QString &rootDir, SettingsObject *settings, - QObject *parent = 0); + BaseInstance(const QString &rootDir, SettingsObject *settings, QObject *parent = 0); public: /// virtual destructor to make sure the destruction is COMPLETE @@ -69,8 +68,8 @@ public: /// be unique. virtual QString id() const; - virtual void setRunning(bool running) const; - virtual bool isRunning() const; + void setRunning(bool running); + bool isRunning() const; /// get the type of this instance QString instanceType() const; @@ -127,30 +126,10 @@ public: { return nullptr; } - + /// Traits. Normally inside the version, depends on instance implementation. virtual QSet <QString> traits() = 0; - /// Get the curent base jar of this instance. By default, it's the - /// versions/$version/$version.jar - QString baseJar() const; - - /// the default base jar of this instance - virtual QString defaultBaseJar() const = 0; - /// the default custom base jar of this instance - virtual QString defaultCustomBaseJar() const = 0; - - /*! - * Whether or not custom base jar is used - */ - bool shouldUseCustomBaseJar() const; - void setShouldUseCustomBaseJar(bool val); - /*! - * The value of the custom base jar - */ - QString customBaseJar() const; - void setCustomBaseJar(QString val); - /** * Gets the time that the instance was last launched. * Stored in milliseconds since epoch. @@ -202,7 +181,7 @@ public: VersionBrokenFlag = 0x01, UpdateAvailable = 0x02 }; - Q_DECLARE_FLAGS(InstanceFlags, InstanceFlag) + Q_DECLARE_FLAGS(InstanceFlags, InstanceFlag); InstanceFlags flags() const; void setFlags(const InstanceFlags &flags); void setFlag(const InstanceFlag flag); @@ -232,7 +211,11 @@ protected slots: void iconUpdated(QString key); protected: - std::shared_ptr<BaseInstancePrivate> inst_d; + QString m_rootDir; + QString m_group; + std::shared_ptr<SettingsObject> m_settings; + InstanceFlags m_flags; + bool m_isRunning = false; }; Q_DECLARE_METATYPE(std::shared_ptr<BaseInstance>) diff --git a/logic/BaseInstance_p.h b/logic/BaseInstance_p.h deleted file mode 100644 index 2958e4e8..00000000 --- a/logic/BaseInstance_p.h +++ /dev/null @@ -1,36 +0,0 @@ -/* Copyright 2013-2014 MultiMC Contributors - * - * 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 <QSet> - -#include "logic/settings/SettingsObject.h" - -#include "BaseInstance.h" - -#define I_D(Class) Class##Private *const d = (Class##Private * const)inst_d.get() - -class BaseInstancePrivate -{ -public: - virtual ~BaseInstancePrivate(){}; - QString m_rootDir; - QString m_group; - std::shared_ptr<SettingsObject> m_settings; - BaseInstance::InstanceFlags m_flags; - bool m_isRunning = false; -}; diff --git a/logic/InstanceFactory.cpp b/logic/InstanceFactory.cpp index 640c02f3..832b8387 100644 --- a/logic/InstanceFactory.cpp +++ b/logic/InstanceFactory.cpp @@ -100,7 +100,6 @@ InstanceFactory::InstCreateError InstanceFactory::createInstance(InstancePtr &in m_settings->set("InstanceType", "OneSix"); inst.reset(new OneSixInstance(instDir, m_settings)); inst->setIntendedVersionId(version->descriptor()); - inst->setShouldUseCustomBaseJar(false); } else if (type == FTBInstance) { @@ -109,14 +108,12 @@ InstanceFactory::InstCreateError InstanceFactory::createInstance(InstancePtr &in m_settings->set("InstanceType", "LegacyFTB"); inst.reset(new LegacyFTBInstance(instDir, m_settings)); inst->setIntendedVersionId(version->descriptor()); - inst->setShouldUseCustomBaseJar(false); } else { m_settings->set("InstanceType", "OneSixFTB"); inst.reset(new OneSixFTBInstance(instDir, m_settings)); inst->setIntendedVersionId(version->descriptor()); - inst->setShouldUseCustomBaseJar(false); } } else diff --git a/logic/InstanceLauncher.cpp b/logic/InstanceLauncher.cpp deleted file mode 100644 index 4e47c592..00000000 --- a/logic/InstanceLauncher.cpp +++ /dev/null @@ -1,94 +0,0 @@ -/* Copyright 2013-2014 MultiMC Contributors - * - * 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 <iostream> - -#include "InstanceLauncher.h" -#include "MultiMC.h" - -#include "gui/ConsoleWindow.h" -#include "gui/dialogs/ProgressDialog.h" - -#include "logic/MinecraftProcess.h" -#include "logic/InstanceList.h" - -InstanceLauncher::InstanceLauncher(QString instId) : QObject(), instId(instId) -{ -} - -void InstanceLauncher::onTerminated() -{ - std::cout << "Minecraft exited" << std::endl; - MMC->quit(); -} - -void InstanceLauncher::onLoginComplete() -{ - // TODO: Fix this. - /* - LoginTask *task = (LoginTask *)QObject::sender(); - auto result = task->getResult(); - auto instance = MMC->instances()->getInstanceById(instId); - proc = instance->prepareForLaunch(result); - if (!proc) - { - // FIXME: report error - return; - } - console = new ConsoleWindow(proc); - connect(console, SIGNAL(isClosing()), this, SLOT(onTerminated())); - - proc->setLogin(result.username, result.session_id); - proc->launch(); - */ -} - -void InstanceLauncher::doLogin(const QString &errorMsg) -{ - // FIXME: Use new account system here... - /* - LoginDialog *loginDlg = new LoginDialog(nullptr, errorMsg); - loginDlg->exec(); - if (loginDlg->result() == QDialog::Accepted) - { - PasswordLogin uInfo{loginDlg->getUsername(), loginDlg->getPassword()}; - - ProgressDialog *tDialog = new ProgressDialog(nullptr); - LoginTask *loginTask = new LoginTask(uInfo, tDialog); - connect(loginTask, SIGNAL(succeeded()), SLOT(onLoginComplete()), Qt::QueuedConnection); - connect(loginTask, SIGNAL(failed(QString)), SLOT(doLogin(QString)), - Qt::QueuedConnection); - tDialog->exec(loginTask); - } - */ - // onLoginComplete(LoginResponse("Offline","Offline", 1)); -} - -int InstanceLauncher::launch() -{ - std::cout << "Launching Instance '" << qPrintable(instId) << "'" << std::endl; - auto instance = MMC->instances()->getInstanceById(instId); - if (!instance) - { - std::cout << "Could not find instance requested. note that you have to specify the ID, " - "not the NAME" << std::endl; - return 1; - } - - std::cout << "Logging in..." << std::endl; - doLogin(""); - - return MMC->exec(); -} diff --git a/logic/InstanceLauncher.h b/logic/InstanceLauncher.h deleted file mode 100644 index 07f86b99..00000000 --- a/logic/InstanceLauncher.h +++ /dev/null @@ -1,44 +0,0 @@ -/* Copyright 2013-2014 MultiMC Contributors - * - * 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 <QObject> - -class MinecraftProcess; -class ConsoleWindow; - -// Commandline instance launcher -class InstanceLauncher : public QObject -{ - Q_OBJECT - -private: - QString instId; - MinecraftProcess *proc; - ConsoleWindow *console; - -public: - InstanceLauncher(QString instId); - -private -slots: - void onTerminated(); - void onLoginComplete(); - void doLogin(const QString &errorMsg); - -public: - int launch(); -}; diff --git a/logic/JarUtils.cpp b/logic/JarUtils.cpp new file mode 100644 index 00000000..3b4f780a --- /dev/null +++ b/logic/JarUtils.cpp @@ -0,0 +1,161 @@ +#include "JarUtils.h" +#include <quazip.h> +#include <quazipfile.h> +#include <JlCompress.h> +#include <logger/QsLog.h> + +namespace JarUtils { + +bool mergeZipFiles(QuaZip *into, QFileInfo from, QSet<QString> &contained, + std::function<bool(QString)> filter) +{ + QuaZip modZip(from.filePath()); + modZip.open(QuaZip::mdUnzip); + + QuaZipFile fileInsideMod(&modZip); + QuaZipFile zipOutFile(into); + for (bool more = modZip.goToFirstFile(); more; more = modZip.goToNextFile()) + { + QString filename = modZip.getCurrentFileName(); + if (!filter(filename)) + { + QLOG_INFO() << "Skipping file " << filename << " from " + << from.fileName() << " - filtered"; + continue; + } + if (contained.contains(filename)) + { + QLOG_INFO() << "Skipping already contained file " << filename << " from " + << from.fileName(); + continue; + } + contained.insert(filename); + QLOG_INFO() << "Adding file " << filename << " from " << from.fileName(); + + if (!fileInsideMod.open(QIODevice::ReadOnly)) + { + QLOG_ERROR() << "Failed to open " << filename << " from " << from.fileName(); + return false; + } + + QuaZipNewInfo info_out(fileInsideMod.getActualFileName()); + + if (!zipOutFile.open(QIODevice::WriteOnly, info_out)) + { + QLOG_ERROR() << "Failed to open " << filename << " in the jar"; + fileInsideMod.close(); + return false; + } + if (!JlCompress::copyData(fileInsideMod, zipOutFile)) + { + zipOutFile.close(); + fileInsideMod.close(); + QLOG_ERROR() << "Failed to copy data of " << filename << " into the jar"; + return false; + } + zipOutFile.close(); + fileInsideMod.close(); + } + return true; +} + +bool createModdedJar(QString sourceJarPath, QString targetJarPath, const QList<Mod>& mods) +{ + QuaZip zipOut(targetJarPath); + if (!zipOut.open(QuaZip::mdCreate)) + { + QFile::remove(targetJarPath); + QLOG_ERROR() << "Failed to open the minecraft.jar for modding"; + return false; + } + // Files already added to the jar. + // These files will be skipped. + QSet<QString> addedFiles; + + // Modify the jar + QListIterator<Mod> i(mods); + i.toBack(); + while (i.hasPrevious()) + { + const Mod &mod = i.previous(); + // do not merge disabled mods. + if (!mod.enabled()) + continue; + if (mod.type() == Mod::MOD_ZIPFILE) + { + if (!mergeZipFiles(&zipOut, mod.filename(), addedFiles, noFilter)) + { + zipOut.close(); + QFile::remove(targetJarPath); + QLOG_ERROR() << "Failed to add" << mod.filename().fileName() << "to the jar."; + return false; + } + } + else if (mod.type() == Mod::MOD_SINGLEFILE) + { + auto filename = mod.filename(); + if (!JlCompress::compressFile(&zipOut, filename.absoluteFilePath(), + filename.fileName())) + { + zipOut.close(); + QFile::remove(targetJarPath); + QLOG_ERROR() << "Failed to add" << mod.filename().fileName() << "to the jar."; + return false; + } + addedFiles.insert(filename.fileName()); + QLOG_INFO() << "Adding file " << filename.fileName() << " from " + << filename.absoluteFilePath(); + } + else if (mod.type() == Mod::MOD_FOLDER) + { + auto filename = mod.filename(); + QString what_to_zip = filename.absoluteFilePath(); + QDir dir(what_to_zip); + dir.cdUp(); + QString parent_dir = dir.absolutePath(); + if (!JlCompress::compressSubDir(&zipOut, what_to_zip, parent_dir, true, addedFiles)) + { + zipOut.close(); + QFile::remove(targetJarPath); + QLOG_ERROR() << "Failed to add" << mod.filename().fileName() << "to the jar."; + return false; + } + QLOG_INFO() << "Adding folder " << filename.fileName() << " from " + << filename.absoluteFilePath(); + } + } + + if (!mergeZipFiles(&zipOut, QFileInfo(sourceJarPath), addedFiles, metaInfFilter)) + { + zipOut.close(); + QFile::remove(targetJarPath); + QLOG_ERROR() << "Failed to insert minecraft.jar contents."; + return false; + } + + // Recompress the jar + zipOut.close(); + if (zipOut.getZipError() != 0) + { + QFile::remove(targetJarPath); + QLOG_ERROR() << "Failed to finalize minecraft.jar!"; + return false; + } + return true; +} + +bool noFilter(QString) +{ + return true; +} + +bool metaInfFilter(QString key) +{ + if(key.contains("META-INF")) + { + return false; + } + return true; +} + +} diff --git a/logic/JarUtils.h b/logic/JarUtils.h new file mode 100644 index 00000000..2e8bd2a7 --- /dev/null +++ b/logic/JarUtils.h @@ -0,0 +1,18 @@ +#pragma once +#include <QString> +#include <QFileInfo> +#include <QSet> +#include "Mod.h" +#include <functional> + +class QuaZip; +namespace JarUtils +{ + bool noFilter(QString); + bool metaInfFilter(QString key); + + bool mergeZipFiles(QuaZip *into, QFileInfo from, QSet<QString> &contained, + std::function<bool(QString)> filter); + + bool createModdedJar(QString sourceJarPath, QString targetJarPath, const QList<Mod>& mods); +} diff --git a/logic/LegacyInstance.cpp b/logic/LegacyInstance.cpp index 468110da..7752229a 100644 --- a/logic/LegacyInstance.cpp +++ b/logic/LegacyInstance.cpp @@ -23,7 +23,6 @@ #include "MultiMC.h" #include "LegacyInstance.h" -#include "LegacyInstance_p.h" #include "logic/MinecraftProcess.h" #include "logic/LegacyUpdate.h" @@ -36,15 +35,23 @@ #include <gui/pages/NotesPage.h> #include <gui/pages/ScreenshotsPage.h> -LegacyInstance::LegacyInstance(const QString &rootDir, SettingsObject *settings, - QObject *parent) - : BaseInstance(new LegacyInstancePrivate(), rootDir, settings, parent) +LegacyInstance::LegacyInstance(const QString &rootDir, SettingsObject *settings, QObject *parent) + : BaseInstance(rootDir, settings, parent) { settings->registerSetting("NeedsRebuild", true); settings->registerSetting("ShouldUpdate", false); settings->registerSetting("JarVersion", "Unknown"); settings->registerSetting("LwjglVersion", "2.9.0"); settings->registerSetting("IntendedJarVersion", ""); + /* + * custom base jar has no default. it is determined in code... see the accessor methods for + *it + * + * for instances that DO NOT have the CustomBaseJar setting (legacy instances), + * [.]minecraft/bin/mcbackup.jar is the default base jar + */ + settings->registerSetting("UseCustomBaseJar", true); + settings->registerSetting("CustomBaseJar", ""); } QList<BasePage *> LegacyInstance::getPages() @@ -69,6 +76,46 @@ QString LegacyInstance::dialogTitle() return tr("Edit Instance (%1)").arg(name()); } +QString LegacyInstance::baseJar() const +{ + bool customJar = m_settings->get("UseCustomBaseJar").toBool(); + if (customJar) + { + return customBaseJar(); + } + else + return defaultBaseJar(); +} + +QString LegacyInstance::customBaseJar() const +{ + QString value = m_settings->get("CustomBaseJar").toString(); + if (value.isNull() || value.isEmpty()) + { + return defaultCustomBaseJar(); + } + return value; +} + +void LegacyInstance::setCustomBaseJar(QString val) +{ + if (val.isNull() || val.isEmpty() || val == defaultCustomBaseJar()) + m_settings->reset("CustomBaseJar"); + else + m_settings->set("CustomBaseJar", val); +} + +void LegacyInstance::setShouldUseCustomBaseJar(bool val) +{ + m_settings->set("UseCustomBaseJar", val); +} + +bool LegacyInstance::shouldUseCustomBaseJar() const +{ + return m_settings->get("UseCustomBaseJar").toBool(); +} + + std::shared_ptr<Task> LegacyInstance::doUpdate() { // make sure the jar mods list is initialized by asking for it. @@ -113,26 +160,24 @@ void LegacyInstance::cleanupAfterRun() std::shared_ptr<ModList> LegacyInstance::coreModList() { - I_D(LegacyInstance); - if (!d->core_mod_list) + if (!core_mod_list) { - d->core_mod_list.reset(new ModList(coreModsDir())); + core_mod_list.reset(new ModList(coreModsDir())); } - d->core_mod_list->update(); - return d->core_mod_list; + core_mod_list->update(); + return core_mod_list; } std::shared_ptr<ModList> LegacyInstance::jarModList() { - I_D(LegacyInstance); - if (!d->jar_mod_list) + if (!jar_mod_list) { auto list = new ModList(jarModsDir(), modListFile()); connect(list, SIGNAL(changed()), SLOT(jarModsChanged())); - d->jar_mod_list.reset(list); + jar_mod_list.reset(list); } - d->jar_mod_list->update(); - return d->jar_mod_list; + jar_mod_list->update(); + return jar_mod_list; } void LegacyInstance::jarModsChanged() @@ -143,24 +188,22 @@ void LegacyInstance::jarModsChanged() std::shared_ptr<ModList> LegacyInstance::loaderModList() { - I_D(LegacyInstance); - if (!d->loader_mod_list) + if (!loader_mod_list) { - d->loader_mod_list.reset(new ModList(loaderModsDir())); + loader_mod_list.reset(new ModList(loaderModsDir())); } - d->loader_mod_list->update(); - return d->loader_mod_list; + loader_mod_list->update(); + return loader_mod_list; } std::shared_ptr<ModList> LegacyInstance::texturePackList() { - I_D(LegacyInstance); - if (!d->texture_pack_list) + if (!texture_pack_list) { - d->texture_pack_list.reset(new ModList(texturePacksDir())); + texture_pack_list.reset(new ModList(texturePacksDir())); } - d->texture_pack_list->update(); - return d->texture_pack_list; + texture_pack_list->update(); + return texture_pack_list; } QString LegacyInstance::jarModsDir() const @@ -219,38 +262,32 @@ QString LegacyInstance::instanceConfigFolder() const bool LegacyInstance::shouldRebuild() const { - I_D(LegacyInstance); - return d->m_settings->get("NeedsRebuild").toBool(); + return m_settings->get("NeedsRebuild").toBool(); } void LegacyInstance::setShouldRebuild(bool val) { - I_D(LegacyInstance); - d->m_settings->set("NeedsRebuild", val); + m_settings->set("NeedsRebuild", val); } QString LegacyInstance::currentVersionId() const { - I_D(LegacyInstance); - return d->m_settings->get("JarVersion").toString(); + return m_settings->get("JarVersion").toString(); } QString LegacyInstance::lwjglVersion() const { - I_D(LegacyInstance); - return d->m_settings->get("LwjglVersion").toString(); + return m_settings->get("LwjglVersion").toString(); } void LegacyInstance::setLWJGLVersion(QString val) { - I_D(LegacyInstance); - d->m_settings->set("LwjglVersion", val); + m_settings->set("LwjglVersion", val); } QString LegacyInstance::intendedVersionId() const { - I_D(LegacyInstance); - return d->m_settings->get("IntendedJarVersion").toString(); + return m_settings->get("IntendedJarVersion").toString(); } bool LegacyInstance::setIntendedVersionId(QString version) diff --git a/logic/LegacyInstance.h b/logic/LegacyInstance.h index d21d2ff4..b91be7c1 100644 --- a/logic/LegacyInstance.h +++ b/logic/LegacyInstance.h @@ -56,6 +56,27 @@ public: QString resourceDir() const; virtual QString instanceConfigFolder() const override; + /// Get the curent base jar of this instance. By default, it's the + /// versions/$version/$version.jar + QString baseJar() const; + + /// the default base jar of this instance + QString defaultBaseJar() const; + /// the default custom base jar of this instance + QString defaultCustomBaseJar() const; + + /*! + * Whether or not custom base jar is used + */ + bool shouldUseCustomBaseJar() const; + void setShouldUseCustomBaseJar(bool val); + + /*! + * The value of the custom base jar + */ + QString customBaseJar() const; + void setCustomBaseJar(QString val); + /*! * Whether or not the instance's minecraft.jar needs to be rebuilt. * If this is true, when the instance launches, its jar mods will be @@ -92,11 +113,14 @@ public: virtual bool prepareForLaunch(AuthSessionPtr account, QString & launchScript) override; virtual void cleanupAfterRun() override; - virtual QString defaultBaseJar() const override; - virtual QString defaultCustomBaseJar() const override; - virtual QString getStatusbarDescription() override; +protected: + std::shared_ptr<ModList> jar_mod_list; + std::shared_ptr<ModList> core_mod_list; + std::shared_ptr<ModList> loader_mod_list; + std::shared_ptr<ModList> texture_pack_list; + protected slots: virtual void jarModsChanged(); diff --git a/logic/LegacyInstance_p.h b/logic/LegacyInstance_p.h deleted file mode 100644 index 83bcecc5..00000000 --- a/logic/LegacyInstance_p.h +++ /dev/null @@ -1,32 +0,0 @@ -/* Copyright 2013-2014 MultiMC Contributors - * - * 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/settings/SettingsObject.h" -#include <memory> - -#include "BaseInstance_p.h" -#include "ModList.h" - -class LegacyInstancePrivate : public BaseInstancePrivate -{ -public: - virtual ~LegacyInstancePrivate() {}; - std::shared_ptr<ModList> jar_mod_list; - std::shared_ptr<ModList> core_mod_list; - std::shared_ptr<ModList> loader_mod_list; - std::shared_ptr<ModList> texture_pack_list; -}; diff --git a/logic/LegacyUpdate.cpp b/logic/LegacyUpdate.cpp index de5c19c0..10128f57 100644 --- a/logic/LegacyUpdate.cpp +++ b/logic/LegacyUpdate.cpp @@ -30,6 +30,7 @@ #include "logger/QsLog.h" #include "logic/net/URLConstants.h" +#include "JarUtils.h" LegacyUpdate::LegacyUpdate(BaseInstance *inst, QObject *parent) : Task(parent), m_inst(inst) @@ -38,25 +39,7 @@ LegacyUpdate::LegacyUpdate(BaseInstance *inst, QObject *parent) : Task(parent), void LegacyUpdate::executeTask() { - /* - if(m_only_prepare) - { - // FIXME: think this through some more. - LegacyInstance *inst = (LegacyInstance *)m_inst; - if (!inst->shouldUpdate() || inst->shouldUseCustomBaseJar()) - { - ModTheJar(); - } - else - { - emitSucceeded(); - } - } - else - { - */ fmllibsStart(); - //} } void LegacyUpdate::fmllibsStart() @@ -415,65 +398,6 @@ void LegacyUpdate::jarFailed() emitFailed("Failed to download the minecraft jar. Try again later."); } -bool LegacyUpdate::MergeZipFiles(QuaZip *into, QFileInfo from, QSet<QString> &contained, - MetainfAction metainf) -{ - setStatus(tr("Installing mods: Adding ") + from.fileName() + " ..."); - - QuaZip modZip(from.filePath()); - modZip.open(QuaZip::mdUnzip); - - QuaZipFile fileInsideMod(&modZip); - QuaZipFile zipOutFile(into); - for (bool more = modZip.goToFirstFile(); more; more = modZip.goToNextFile()) - { - QString filename = modZip.getCurrentFileName(); - if (filename.contains("META-INF") && metainf == LegacyUpdate::IgnoreMetainf) - { - QLOG_INFO() << "Skipping META-INF " << filename << " from " << from.fileName(); - continue; - } - if (contained.contains(filename)) - { - QLOG_INFO() << "Skipping already contained file " << filename << " from " - << from.fileName(); - continue; - } - contained.insert(filename); - QLOG_INFO() << "Adding file " << filename << " from " << from.fileName(); - - if (!fileInsideMod.open(QIODevice::ReadOnly)) - { - QLOG_ERROR() << "Failed to open " << filename << " from " << from.fileName(); - return false; - } - /* - QuaZipFileInfo old_info; - fileInsideMod.getFileInfo(&old_info); - */ - QuaZipNewInfo info_out(fileInsideMod.getActualFileName()); - /* - info_out.externalAttr = old_info.externalAttr; - */ - if (!zipOutFile.open(QIODevice::WriteOnly, info_out)) - { - QLOG_ERROR() << "Failed to open " << filename << " in the jar"; - fileInsideMod.close(); - return false; - } - if (!JlCompress::copyData(fileInsideMod, zipOutFile)) - { - zipOutFile.close(); - fileInsideMod.close(); - QLOG_ERROR() << "Failed to copy data of " << filename << " into the jar"; - return false; - } - zipOutFile.close(); - fileInsideMod.close(); - } - return true; -} - void LegacyUpdate::ModTheJar() { LegacyInstance *inst = (LegacyInstance *)m_inst; @@ -531,85 +455,13 @@ void LegacyUpdate::ModTheJar() // TaskStep(); // STEP 1 setStatus(tr("Installing mods: Opening minecraft.jar ...")); - QuaZip zipOut(runnableJar.filePath()); - if (!zipOut.open(QuaZip::mdCreate)) - { - QFile::remove(runnableJar.filePath()); - emitFailed("Failed to open the minecraft.jar for modding"); - return; - } - // Files already added to the jar. - // These files will be skipped. - QSet<QString> addedFiles; - - // Modify the jar - setStatus(tr("Installing mods: Adding mod files...")); - for (int i = modList->size() - 1; i >= 0; i--) - { - auto &mod = modList->operator[](i); - - // do not merge disabled mods. - if (!mod.enabled()) - continue; - - if (mod.type() == Mod::MOD_ZIPFILE) - { - if (!MergeZipFiles(&zipOut, mod.filename(), addedFiles, LegacyUpdate::KeepMetainf)) - { - zipOut.close(); - QFile::remove(runnableJar.filePath()); - emitFailed("Failed to add " + mod.filename().fileName() + " to the jar."); - return; - } - } - else if (mod.type() == Mod::MOD_SINGLEFILE) - { - auto filename = mod.filename(); - if (!JlCompress::compressFile(&zipOut, filename.absoluteFilePath(), - filename.fileName())) - { - zipOut.close(); - QFile::remove(runnableJar.filePath()); - emitFailed("Failed to add " + filename.fileName() + " to the jar"); - return; - } - addedFiles.insert(filename.fileName()); - QLOG_INFO() << "Adding file " << filename.fileName() << " from " - << filename.absoluteFilePath(); - } - else if (mod.type() == Mod::MOD_FOLDER) - { - auto filename = mod.filename(); - QString what_to_zip = filename.absoluteFilePath(); - QDir dir(what_to_zip); - dir.cdUp(); - QString parent_dir = dir.absolutePath(); - if (!JlCompress::compressSubDir(&zipOut, what_to_zip, parent_dir, true, addedFiles)) - { - zipOut.close(); - QFile::remove(runnableJar.filePath()); - emitFailed("Failed to add " + filename.fileName() + " to the jar"); - return; - } - QLOG_INFO() << "Adding folder " << filename.fileName() << " from " - << filename.absoluteFilePath(); - } - } - - if (!MergeZipFiles(&zipOut, baseJar, addedFiles, LegacyUpdate::IgnoreMetainf)) - { - zipOut.close(); - QFile::remove(runnableJar.filePath()); - emitFailed("Failed to insert minecraft.jar contents."); - return; - } + const auto & mods = modList->allMods(); + QString outputJarPath = runnableJar.filePath(); + QString inputJarPath = baseJar.filePath(); - // Recompress the jar - zipOut.close(); - if (zipOut.getZipError() != 0) + if(!JarUtils::createModdedJar(inputJarPath, outputJarPath, mods)) { - QFile::remove(runnableJar.filePath()); - emitFailed("Failed to finalize minecraft.jar!"); + emitFailed(tr("Failed to create the custom Minecraft jar file.")); return; } inst->setShouldRebuild(false); diff --git a/logic/LegacyUpdate.h b/logic/LegacyUpdate.h index da538d2f..8041305a 100644 --- a/logic/LegacyUpdate.h +++ b/logic/LegacyUpdate.h @@ -54,15 +54,6 @@ slots: void ModTheJar(); private: - enum MetainfAction - { - KeepMetainf, // the META-INF folder will be added from the merged jar - IgnoreMetainf // the META-INF from the merged jar will be ignored - }; - bool MergeZipFiles(QuaZip *into, QFileInfo from, QSet<QString> &contained, - MetainfAction metainf); - -private: std::shared_ptr<QNetworkReply> m_reply; diff --git a/logic/ModList.h b/logic/ModList.h index e7320df5..2409a31a 100644 --- a/logic/ModList.h +++ b/logic/ModList.h @@ -126,6 +126,11 @@ public: return m_dir; } + const QList<Mod> & allMods() + { + return mods; + } + private: void internalSort(QList<Mod> & what); struct OrderItem diff --git a/logic/OneSixFTBInstance.cpp b/logic/OneSixFTBInstance.cpp index d1585155..bf1361dd 100644 --- a/logic/OneSixFTBInstance.cpp +++ b/logic/OneSixFTBInstance.cpp @@ -6,7 +6,6 @@ #include "tasks/SequentialTask.h" #include "forge/ForgeInstaller.h" #include "forge/ForgeVersionList.h" -#include "OneSixInstance_p.h" #include "MultiMC.h" #include "pathutils.h" diff --git a/logic/OneSixInstance.cpp b/logic/OneSixInstance.cpp index dbf47ffb..40b87d9e 100644 --- a/logic/OneSixInstance.cpp +++ b/logic/OneSixInstance.cpp @@ -21,7 +21,6 @@ #include "logic/OneSixInstance.h" -#include "logic/OneSixInstance_p.h" #include "logic/OneSixUpdate.h" #include "logic/minecraft/InstanceVersion.h" #include "minecraft/VersionBuildError.h" @@ -39,13 +38,11 @@ #include "gui/pages/ScreenshotsPage.h" #include "gui/pages/OtherLogsPage.h" -OneSixInstance::OneSixInstance(const QString &rootDir, SettingsObject *settings, - QObject *parent) - : BaseInstance(new OneSixInstancePrivate(), rootDir, settings, parent) +OneSixInstance::OneSixInstance(const QString &rootDir, SettingsObject *settings, QObject *parent) + : BaseInstance(rootDir, settings, parent) { - I_D(OneSixInstance); - d->m_settings->registerSetting("IntendedVersion", ""); - d->version.reset(new InstanceVersion(this, this)); + m_settings->registerSetting("IntendedVersion", ""); + version.reset(new InstanceVersion(this, this)); } void OneSixInstance::init() @@ -184,8 +181,6 @@ QDir OneSixInstance::reconstructAssets(std::shared_ptr<InstanceVersion> version) QStringList OneSixInstance::processMinecraftArgs(AuthSessionPtr session) { - I_D(OneSixInstance); - auto version = d->version; QString args_pattern = version->minecraftArguments; for (auto tweaker : version->tweakers) { @@ -207,7 +202,7 @@ QStringList OneSixInstance::processMinecraftArgs(AuthSessionPtr session) QString absRootDir = QDir(minecraftRoot()).absolutePath(); token_mapping["game_directory"] = absRootDir; QString absAssetsDir = QDir("assets/").absolutePath(); - token_mapping["game_assets"] = reconstructAssets(d->version).absolutePath(); + token_mapping["game_assets"] = reconstructAssets(version).absolutePath(); token_mapping["user_properties"] = session->serializeUserProperties(); token_mapping["user_type"] = session->user_type; @@ -225,13 +220,11 @@ QStringList OneSixInstance::processMinecraftArgs(AuthSessionPtr session) bool OneSixInstance::prepareForLaunch(AuthSessionPtr session, QString &launchScript) { - I_D(OneSixInstance); QIcon icon = MMC->icons()->getIcon(iconKey()); auto pixmap = icon.pixmap(128, 128); pixmap.save(PathCombine(minecraftRoot(), "icon.png"), "PNG"); - auto version = d->version; if (!version) return nullptr; @@ -242,20 +235,15 @@ bool OneSixInstance::prepareForLaunch(AuthSessionPtr session, QString &launchScr { launchScript += "cp " + librariesPath().absoluteFilePath(lib->storagePath()) + "\n"; } - QString minecraftjarpath; if (version->hasJarMods()) { - for (auto jarmod : version->jarMods) - { - launchScript += "cp " + jarmodsPath().absoluteFilePath(jarmod->name) + "\n"; - } - minecraftjarpath = version->id + "/" + version->id + "-stripped.jar"; + launchScript += "cp " + QDir(instanceRoot()).absoluteFilePath("temp.jar") + "\n"; } else { - minecraftjarpath = version->id + "/" + version->id + ".jar"; + QString relpath = version->id + "/" + version->id + ".jar"; + launchScript += "cp " + versionsPath().absoluteFilePath(relpath) + "\n"; } - launchScript += "cp " + versionsPath().absoluteFilePath(minecraftjarpath) + "\n"; } if (!version->mainClass.isEmpty()) { @@ -320,46 +308,42 @@ void OneSixInstance::cleanupAfterRun() std::shared_ptr<ModList> OneSixInstance::loaderModList() { - I_D(OneSixInstance); - if (!d->loader_mod_list) + if (!loader_mod_list) { - d->loader_mod_list.reset(new ModList(loaderModsDir())); + loader_mod_list.reset(new ModList(loaderModsDir())); } - d->loader_mod_list->update(); - return d->loader_mod_list; + loader_mod_list->update(); + return loader_mod_list; } std::shared_ptr<ModList> OneSixInstance::coreModList() { - I_D(OneSixInstance); - if (!d->core_mod_list) + if (!core_mod_list) { - d->core_mod_list.reset(new ModList(coreModsDir())); + core_mod_list.reset(new ModList(coreModsDir())); } - d->core_mod_list->update(); - return d->core_mod_list; + core_mod_list->update(); + return core_mod_list; } std::shared_ptr<ModList> OneSixInstance::resourcePackList() { - I_D(OneSixInstance); - if (!d->resource_pack_list) + if (!resource_pack_list) { - d->resource_pack_list.reset(new ModList(resourcePacksDir())); + resource_pack_list.reset(new ModList(resourcePacksDir())); } - d->resource_pack_list->update(); - return d->resource_pack_list; + resource_pack_list->update(); + return resource_pack_list; } std::shared_ptr<ModList> OneSixInstance::texturePackList() { - I_D(OneSixInstance); - if (!d->texture_pack_list) + if (!texture_pack_list) { - d->texture_pack_list.reset(new ModList(texturePacksDir())); + texture_pack_list.reset(new ModList(texturePacksDir())); } - d->texture_pack_list->update(); - return d->texture_pack_list; + texture_pack_list->update(); + return texture_pack_list; } bool OneSixInstance::setIntendedVersionId(QString version) @@ -386,22 +370,18 @@ bool OneSixInstance::shouldUpdate() const bool OneSixInstance::versionIsCustom() { - I_D(const OneSixInstance); - auto ver = d->version; - if (ver) + if (version) { - return !ver->isVanilla(); + return !version->isVanilla(); } return false; } bool OneSixInstance::versionIsFTBPack() { - I_D(const OneSixInstance); - auto ver = d->version; - if (ver) + if (version) { - return ver->hasFtbPack(); + return version->hasFtbPack(); } return false; } @@ -413,11 +393,10 @@ QString OneSixInstance::currentVersionId() const void OneSixInstance::reloadVersion() { - I_D(OneSixInstance); try { - d->version->reload(externalPatches()); + version->reload(externalPatches()); unsetFlag(VersionBrokenFlag); emit versionReloaded(); } @@ -426,7 +405,7 @@ void OneSixInstance::reloadVersion() } catch (MMCError &error) { - d->version->clear(); + version->clear(); setFlag(VersionBrokenFlag); // TODO: rethrow to show some error message(s)? emit versionReloaded(); @@ -436,25 +415,13 @@ void OneSixInstance::reloadVersion() void OneSixInstance::clearVersion() { - I_D(OneSixInstance); - d->version->clear(); + version->clear(); emit versionReloaded(); } std::shared_ptr<InstanceVersion> OneSixInstance::getFullVersion() const { - I_D(const OneSixInstance); - return d->version; -} - -QString OneSixInstance::defaultBaseJar() const -{ - return "versions/" + intendedVersionId() + "/" + intendedVersionId() + ".jar"; -} - -QString OneSixInstance::defaultCustomBaseJar() const -{ - return PathCombine(instanceRoot(), "custom.jar"); + return version; } QString OneSixInstance::getStatusbarDescription() diff --git a/logic/OneSixInstance.h b/logic/OneSixInstance.h index d751ffc8..70726208 100644 --- a/logic/OneSixInstance.h +++ b/logic/OneSixInstance.h @@ -42,7 +42,7 @@ public: std::shared_ptr<ModList> texturePackList() override; virtual QSet<QString> traits(); - + ////// Directories and files ////// QString jarModsDir() const; QString resourcePacksDir() const; @@ -67,26 +67,23 @@ public: /** * reload the full version json files. - * + * * throws various exceptions :3 */ void reloadVersion(); - + /// clears all version information in preparation for an update void clearVersion(); - + /// get the current full version info std::shared_ptr<InstanceVersion> getFullVersion() 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 defaultBaseJar() const override; - virtual QString defaultCustomBaseJar() const override; - virtual QString getStatusbarDescription() override; virtual QDir jarmodsPath() const; @@ -107,6 +104,14 @@ signals: private: QStringList processMinecraftArgs(AuthSessionPtr account); QDir reconstructAssets(std::shared_ptr<InstanceVersion> version); + +protected: + std::shared_ptr<InstanceVersion> version; + std::shared_ptr<ModList> jar_mod_list; + std::shared_ptr<ModList> loader_mod_list; + std::shared_ptr<ModList> core_mod_list; + std::shared_ptr<ModList> resource_pack_list; + std::shared_ptr<ModList> texture_pack_list; }; Q_DECLARE_METATYPE(std::shared_ptr<OneSixInstance>) diff --git a/logic/OneSixInstance_p.h b/logic/OneSixInstance_p.h deleted file mode 100644 index 3fa12baf..00000000 --- a/logic/OneSixInstance_p.h +++ /dev/null @@ -1,33 +0,0 @@ -/* Copyright 2013-2014 MultiMC Contributors - * - * 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 "logic/BaseInstance_p.h" - -class ModList; -class InstanceVersion; - -class OneSixInstancePrivate : public BaseInstancePrivate -{ -public: - virtual ~OneSixInstancePrivate() {}; - std::shared_ptr<InstanceVersion> version; - std::shared_ptr<ModList> jar_mod_list; - std::shared_ptr<ModList> loader_mod_list; - std::shared_ptr<ModList> core_mod_list; - std::shared_ptr<ModList> resource_pack_list; - std::shared_ptr<ModList> texture_pack_list; -}; diff --git a/logic/OneSixUpdate.cpp b/logic/OneSixUpdate.cpp index 380d5dab..fe8cf3b5 100644 --- a/logic/OneSixUpdate.cpp +++ b/logic/OneSixUpdate.cpp @@ -33,6 +33,7 @@ #include "logic/forge/ForgeMirrors.h" #include "logic/net/URLConstants.h" #include "logic/assets/AssetsUtils.h" +#include "JarUtils.h" OneSixUpdate::OneSixUpdate(OneSixInstance *inst, QObject *parent) : Task(parent), m_inst(inst) { @@ -287,23 +288,44 @@ void OneSixUpdate::jarlibFinished() OneSixInstance *inst = (OneSixInstance *)m_inst; std::shared_ptr<InstanceVersion> version = inst->getFullVersion(); + // nuke obsolete stripped jar(s) if needed + QString version_id = version->id; + QString strippedPath = version_id + "/" + version_id + "-stripped.jar"; + QFile strippedJar(strippedPath); + if(strippedJar.exists()) + { + strippedJar.remove(); + } + auto finalJarPath = QDir(m_inst->instanceRoot()).absoluteFilePath("temp.jar"); + QFile finalJar(finalJarPath); + if(finalJar.exists()) + { + if(!finalJar.remove()) + { + emitFailed(tr("Couldn't remove stale jar file: %1").arg(finalJarPath)); + return; + } + } + // create stripped jar, if needed if (version->hasJarMods()) { - // FIXME: good candidate for moving elsewhere (jar location resolving/version caching). - QString version_id = version->id; + auto sourceJarPath = m_inst->versionsPath().absoluteFilePath(version->id + "/" + version->id + ".jar"); QString localPath = version_id + "/" + version_id + ".jar"; - QString strippedPath = version_id + "/" + version_id + "-stripped.jar"; auto metacache = MMC->metacache(); auto entry = metacache->resolveEntry("versions", localPath); - auto entryStripped = metacache->resolveEntry("versions", strippedPath); - QString fullJarPath = entry->getFullPath(); - QString fullStrippedJarPath = entryStripped->getFullPath(); - QFileInfo finfo(fullStrippedJarPath); - if (entry->md5sum != jarHashOnEntry || !finfo.exists()) + //FIXME: remove need to convert to different objects here + 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)) { - stripJar(fullJarPath, fullStrippedJarPath); + emitFailed(tr("Failed to create the custom Minecraft jar file.")); + return; } } if (version->traits.contains("legacyFML")) @@ -324,87 +346,6 @@ void OneSixUpdate::jarlibFailed() tr("Failed to download the following files:\n%1\n\nPlease try again.").arg(failed_all)); } -void OneSixUpdate::stripJar(QString origPath, QString newPath) -{ - QFileInfo runnableJar(newPath); - if (runnableJar.exists() && !QFile::remove(runnableJar.filePath())) - { - emitFailed("Failed to delete old minecraft.jar"); - return; - } - - // TaskStep(); // STEP 1 - setStatus(tr("Creating stripped jar: Opening minecraft.jar ...")); - - QuaZip zipOut(runnableJar.filePath()); - if (!zipOut.open(QuaZip::mdCreate)) - { - QFile::remove(runnableJar.filePath()); - emitFailed("Failed to open the minecraft.jar for stripping"); - return; - } - // Modify the jar - setStatus(tr("Creating stripped jar: Adding files...")); - if (!MergeZipFiles(&zipOut, origPath)) - { - zipOut.close(); - QFile::remove(runnableJar.filePath()); - emitFailed("Failed to add " + origPath + " to the jar."); - return; - } -} - -bool OneSixUpdate::MergeZipFiles(QuaZip *into, QString from) -{ - setStatus(tr("Installing mods: Adding ") + from + " ..."); - - QuaZip modZip(from); - modZip.open(QuaZip::mdUnzip); - - QuaZipFile fileInsideMod(&modZip); - QuaZipFile zipOutFile(into); - for (bool more = modZip.goToFirstFile(); more; more = modZip.goToNextFile()) - { - QString filename = modZip.getCurrentFileName(); - if (filename.contains("META-INF")) - { - QLOG_INFO() << "Skipping META-INF " << filename << " from " << from; - continue; - } - QLOG_INFO() << "Adding file " << filename << " from " << from; - - if (!fileInsideMod.open(QIODevice::ReadOnly)) - { - QLOG_ERROR() << "Failed to open " << filename << " from " << from; - return false; - } - /* - QuaZipFileInfo old_info; - fileInsideMod.getFileInfo(&old_info); - */ - QuaZipNewInfo info_out(fileInsideMod.getActualFileName()); - /* - info_out.externalAttr = old_info.externalAttr; - */ - if (!zipOutFile.open(QIODevice::WriteOnly, info_out)) - { - QLOG_ERROR() << "Failed to open " << filename << " in the jar"; - fileInsideMod.close(); - return false; - } - if (!JlCompress::copyData(fileInsideMod, zipOutFile)) - { - zipOutFile.close(); - fileInsideMod.close(); - QLOG_ERROR() << "Failed to copy data of " << filename << " into the jar"; - return false; - } - zipOutFile.close(); - fileInsideMod.close(); - } - return true; -} - void OneSixUpdate::fmllibsStart() { // Get the mod list diff --git a/logic/OneSixUpdate.h b/logic/OneSixUpdate.h index 2cad7408..5bbe86ba 100644 --- a/logic/OneSixUpdate.h +++ b/logic/OneSixUpdate.h @@ -53,8 +53,6 @@ slots: void assetsFinished(); void assetsFailed(); - void stripJar(QString origPath, QString newPath); - bool MergeZipFiles(QuaZip *into, QString from); private: NetJobPtr jarlibDownloadJob; NetJobPtr legacyDownloadJob; @@ -63,7 +61,7 @@ private: std::shared_ptr<MinecraftVersion> targetVersion; /// the task that is spawned for version updates std::shared_ptr<Task> versionUpdateTask; - + OneSixInstance *m_inst = nullptr; QString jarHashOnEntry; QList<FMLlib> fmlLibsToProcess; diff --git a/logic/URNResolver.cpp b/logic/URNResolver.cpp deleted file mode 100644 index b6bdcf41..00000000 --- a/logic/URNResolver.cpp +++ /dev/null @@ -1,98 +0,0 @@ -#include "URNResolver.h" -#include <logger/QsLog.h> -#include "MultiMC.h" -#include "logic/forge/ForgeVersionList.h" -#include "logic/forge/ForgeVersion.h" - -QString unescapeNSS(QString RawNSS) -{ - QString NSS; - NSS.reserve(RawNSS.size()); - enum - { - Normal, - FirstHex, - SecondHex - } ParseState = Normal; - - QByteArray translator(" "); - - for (auto ch : RawNSS) - { - if(ParseState == Normal) - { - if(ch == '%') - { - ParseState = FirstHex; - continue; - } - else - { - NSS.append(ch); - } - } - if(ParseState == FirstHex) - { - translator[0] = ch.toLower().unicode(); - ParseState = SecondHex; - } - else if(ParseState == SecondHex) - { - translator[1] = ch.toLower().unicode(); - auto result = QByteArray::fromHex(translator); - if (result[0] == '\0') - return NSS; - NSS.append(result); - ParseState = Normal; - } - } - return NSS; -} - -bool URNResolver::parse(const QString &URN, QString &NID, QString &NSS) -{ - QRegExp URNPattern( - "^urn:([a-z0-9][a-z0-9-]{0,31}):(([a-z0-9()+,\\-.:=@;$_!*']|%[0-9a-f]{2})+).*", - Qt::CaseInsensitive); - if (URNPattern.indexIn(URN) == -1) - return false; - auto captures = URNPattern.capturedTexts(); - QString RawNID = captures[1]; - QString RawNSS = captures[2]; - - NID = RawNID.toLower(); - NSS = unescapeNSS(RawNSS); - return true; -} - -URNResolver::URNResolver() -{ -} - -QVariant URNResolver::resolve(QString URN) -{ - QString NID, NSS; - parse(URN, NID, NSS); - - if(NID != "x-mmc") - return QVariant(); - auto parts = NSS.split(":"); - if(parts.size() < 1) - return QVariant(); - unsigned int version = parts[0].toUInt(); - switch(version) - { - case 1: - return resolveV1(parts.mid(1)); - default: - return QVariant(); - } -} - -/** - * TODO: implement. - */ -QVariant URNResolver::resolveV1(QStringList parts) -{ - return QVariant(); -} diff --git a/logic/URNResolver.h b/logic/URNResolver.h deleted file mode 100644 index dfc7f5eb..00000000 --- a/logic/URNResolver.h +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once -#include <QString> -#include <QMap> -#include <memory> -#include <QVariant> - -class URNResolver; -typedef std::shared_ptr<URNResolver> URNResolverPtr; - -class URNResolver -{ -public: - URNResolver(); - QVariant resolve (QString URN); - static bool parse (const QString &URN, QString &NID, QString &NSS); -private: - QVariant resolveV1 (QStringList parts); -}; diff --git a/logic/minecraft/VersionFile.cpp b/logic/minecraft/VersionFile.cpp index 311271fe..3e0648cc 100644 --- a/logic/minecraft/VersionFile.cpp +++ b/logic/minecraft/VersionFile.cpp @@ -43,6 +43,7 @@ VersionFilePtr VersionFile::fromJson(const QJsonDocument &doc, const QString &fi } if (!doc.isObject()) { + throw JSONValidationError(filename + " is not an object"); } QJsonObject root = doc.object(); |