diff options
| author | Petr Mrázek <peterix@gmail.com> | 2015-02-04 21:10:10 +0100 |
|---|---|---|
| committer | Petr Mrázek <peterix@gmail.com> | 2015-04-12 20:57:17 +0200 |
| commit | 141e0a02a0a0c4bbc4cc2e900560db5048366104 (patch) | |
| tree | d61b0ac7fedc656d2906f084b9a384b8047e8617 /logic/minecraft | |
| parent | 473971b6e7a79ed38fa68dffacd207fda874fdc0 (diff) | |
| download | PrismLauncher-141e0a02a0a0c4bbc4cc2e900560db5048366104.tar.gz PrismLauncher-141e0a02a0a0c4bbc4cc2e900560db5048366104.tar.bz2 PrismLauncher-141e0a02a0a0c4bbc4cc2e900560db5048366104.zip | |
SCRATCH move things to the right places
Diffstat (limited to 'logic/minecraft')
24 files changed, 4231 insertions, 3 deletions
diff --git a/logic/minecraft/AssetsUtils.cpp b/logic/minecraft/AssetsUtils.cpp new file mode 100644 index 00000000..9f33b1bd --- /dev/null +++ b/logic/minecraft/AssetsUtils.cpp @@ -0,0 +1,217 @@ +/* Copyright 2013-2015 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 <QDir> +#include <QDirIterator> +#include <QCryptographicHash> +#include <QJsonParseError> +#include <QJsonDocument> +#include <QJsonObject> +#include <QVariant> +#include <QDebug> + +#include "AssetsUtils.h" +#include <pathutils.h> + +namespace AssetsUtils +{ +int findLegacyAssets() +{ + QDir assets_dir("assets"); + if (!assets_dir.exists()) + return 0; + assets_dir.setFilter(QDir::AllEntries | QDir::NoDotAndDotDot); + int base_length = assets_dir.path().length(); + + QList<QString> blacklist = {"indexes", "objects", "virtual"}; + + QDirIterator iterator(assets_dir, QDirIterator::Subdirectories); + int found = 0; + while (iterator.hasNext()) + { + QString currentDir = iterator.next(); + currentDir = currentDir.remove(0, base_length + 1); + + bool ignore = false; + for (QString blacklisted : blacklist) + { + if (currentDir.startsWith(blacklisted)) + ignore = true; + } + + if (!iterator.fileInfo().isDir() && !ignore) + { + found++; + } + } + + return found; +} + +/* + * Returns true on success, with index populated + * index is undefined otherwise + */ +bool loadAssetsIndexJson(QString path, AssetsIndex *index) +{ + /* + { + "objects": { + "icons/icon_16x16.png": { + "hash": "bdf48ef6b5d0d23bbb02e17d04865216179f510a", + "size": 3665 + }, + ... + } + } + } + */ + + QFile file(path); + + // Try to open the file and fail if we can't. + // TODO: We should probably report this error to the user. + if (!file.open(QIODevice::ReadOnly)) + { + qCritical() << "Failed to read assets index file" << path; + return false; + } + + // Read the file and close it. + QByteArray jsonData = file.readAll(); + file.close(); + + QJsonParseError parseError; + QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonData, &parseError); + + // Fail if the JSON is invalid. + if (parseError.error != QJsonParseError::NoError) + { + qCritical() << "Failed to parse assets index file:" << parseError.errorString() + << "at offset " << QString::number(parseError.offset); + return false; + } + + // Make sure the root is an object. + if (!jsonDoc.isObject()) + { + qCritical() << "Invalid assets index JSON: Root should be an array."; + return false; + } + + QJsonObject root = jsonDoc.object(); + + QJsonValue isVirtual = root.value("virtual"); + if (!isVirtual.isUndefined()) + { + index->isVirtual = isVirtual.toBool(false); + } + + QJsonValue objects = root.value("objects"); + QVariantMap map = objects.toVariant().toMap(); + + for (QVariantMap::const_iterator iter = map.begin(); iter != map.end(); ++iter) + { + // qDebug() << iter.key(); + + QVariant variant = iter.value(); + QVariantMap nested_objects = variant.toMap(); + + AssetObject object; + + for (QVariantMap::const_iterator nested_iter = nested_objects.begin(); + nested_iter != nested_objects.end(); ++nested_iter) + { + // qDebug() << nested_iter.key() << nested_iter.value().toString(); + QString key = nested_iter.key(); + QVariant value = nested_iter.value(); + + if (key == "hash") + { + object.hash = value.toString(); + } + else if (key == "size") + { + object.size = value.toDouble(); + } + } + + index->objects.insert(iter.key(), object); + } + + 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()) + { + qCritical() << "No assets index file" << indexPath << "; can't reconstruct assets"; + return virtualRoot; + } + + qDebug() << "reconstructAssets" << assetsDir.path() << indexDir.path() + << objectDir.path() << virtualDir.path() << virtualRoot.path(); + + AssetsIndex index; + bool loadAssetsIndex = AssetsUtils::loadAssetsIndexJson(indexPath, &index); + + if (loadAssetsIndex && index.isVirtual) + { + qDebug() << "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(); + // qDebug() << target_dir; + if (!target_dir.exists()) + QDir("").mkpath(target_dir.path()); + + bool couldCopy = original.copy(target_path); + qDebug() << " Copying" << original_path << "to" << target_path + << QString::number(couldCopy); // << original.errorString(); + } + } + + // TODO: Write last used time to virtualRoot/.lastused + } + + return virtualRoot; +} + +} diff --git a/logic/minecraft/AssetsUtils.h b/logic/minecraft/AssetsUtils.h new file mode 100644 index 00000000..ea12136d --- /dev/null +++ b/logic/minecraft/AssetsUtils.h @@ -0,0 +1,39 @@ +/* Copyright 2013-2015 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 <QMap> + +struct AssetObject +{ + QString hash; + qint64 size; +}; + +struct AssetsIndex +{ + QMap<QString, AssetObject> objects; + bool isVirtual = false; +}; + +namespace AssetsUtils +{ +bool loadAssetsIndexJson(QString file, AssetsIndex* index); +int findLegacyAssets(); +/// Reconstruct a virtual assets folder for the given assets ID and return the folder +QDir reconstructAssets(QString assetsId); +} diff --git a/logic/minecraft/JarUtils.cpp b/logic/minecraft/JarUtils.cpp new file mode 100644 index 00000000..59326aba --- /dev/null +++ b/logic/minecraft/JarUtils.cpp @@ -0,0 +1,158 @@ +#include "logic/minecraft/JarUtils.h" +#include <quazip.h> +#include <quazipfile.h> +#include <JlCompress.h> +#include <QDebug> + +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)) + { + qDebug() << "Skipping file " << filename << " from " + << from.fileName() << " - filtered"; + continue; + } + if (contained.contains(filename)) + { + qDebug() << "Skipping already contained file " << filename << " from " + << from.fileName(); + continue; + } + contained.insert(filename); + + if (!fileInsideMod.open(QIODevice::ReadOnly)) + { + qCritical() << "Failed to open " << filename << " from " << from.fileName(); + return false; + } + + QuaZipNewInfo info_out(fileInsideMod.getActualFileName()); + + if (!zipOutFile.open(QIODevice::WriteOnly, info_out)) + { + qCritical() << "Failed to open " << filename << " in the jar"; + fileInsideMod.close(); + return false; + } + if (!JlCompress::copyData(fileInsideMod, zipOutFile)) + { + zipOutFile.close(); + fileInsideMod.close(); + qCritical() << "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); + qCritical() << "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); + qCritical() << "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); + qCritical() << "Failed to add" << mod.filename().fileName() << "to the jar."; + return false; + } + addedFiles.insert(filename.fileName()); + } + 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); + qCritical() << "Failed to add" << mod.filename().fileName() << "to the jar."; + return false; + } + qDebug() << "Adding folder " << filename.fileName() << " from " + << filename.absoluteFilePath(); + } + } + + if (!mergeZipFiles(&zipOut, QFileInfo(sourceJarPath), addedFiles, metaInfFilter)) + { + zipOut.close(); + QFile::remove(targetJarPath); + qCritical() << "Failed to insert minecraft.jar contents."; + return false; + } + + // Recompress the jar + zipOut.close(); + if (zipOut.getZipError() != 0) + { + QFile::remove(targetJarPath); + qCritical() << "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/minecraft/JarUtils.h b/logic/minecraft/JarUtils.h new file mode 100644 index 00000000..2e8bd2a7 --- /dev/null +++ b/logic/minecraft/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/minecraft/LegacyInstance.cpp b/logic/minecraft/LegacyInstance.cpp new file mode 100644 index 00000000..c0fe1513 --- /dev/null +++ b/logic/minecraft/LegacyInstance.cpp @@ -0,0 +1,346 @@ +/* Copyright 2013-2015 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 <QFileInfo> +#include <QDir> +#include <QImage> +#include <logic/settings/Setting.h> +#include <pathutils.h> +#include <cmdutils.h> + +#include "LegacyInstance.h" + +#include "logic/minecraft/LegacyUpdate.h" +#include "logic/icons/IconList.h" +#include "logic/minecraft/MinecraftProcess.h" +#include "gui/pages/LegacyUpgradePage.h" +#include "gui/pages/ModFolderPage.h" +#include "gui/pages/LegacyJarModPage.h" +#include <gui/pages/TexturePackPage.h> +#include <gui/pages/InstanceSettingsPage.h> +#include <gui/pages/NotesPage.h> +#include <gui/pages/ScreenshotsPage.h> + +LegacyInstance::LegacyInstance(SettingsObjectPtr globalSettings, SettingsObjectPtr settings, const QString &rootDir) + : MinecraftInstance(globalSettings, settings, rootDir) +{ + m_lwjglFolderSetting = globalSettings->getSetting("LWJGLDir"); + 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() +{ + QList<BasePage *> values; + // FIXME: actually implement the legacy instance upgrade, then enable this. + //values.append(new LegacyUpgradePage(this)); + values.append(new LegacyJarModPage(this)); + values.append(new ModFolderPage(this, loaderModList(), "mods", "loadermods", tr("Loader mods"), + "Loader-mods")); + values.append(new ModFolderPage(this, coreModList(), "coremods", "coremods", tr("Core mods"), + "Loader-mods")); + values.append(new TexturePackPage(this)); + values.append(new NotesPage(this)); + values.append(new ScreenshotsPage(PathCombine(minecraftRoot(), "screenshots"))); + values.append(new InstanceSettingsPage(this)); + return values; +} + +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. + auto list = jarModList(); + // create an update task + return std::shared_ptr<Task>(new LegacyUpdate(this, this)); +} + +BaseProcess *LegacyInstance::prepareForLaunch(AuthSessionPtr account) +{ + QString launchScript; + QIcon icon = ENV.icons()->getIcon(iconKey()); + auto pixmap = icon.pixmap(128, 128); + pixmap.save(PathCombine(minecraftRoot(), "icon.png"), "PNG"); + + // create the launch script + { + // window size + QString windowParams; + if (settings().get("LaunchMaximized").toBool()) + windowParams = "max"; + else + windowParams = QString("%1x%2") + .arg(settings().get("MinecraftWinWidth").toInt()) + .arg(settings().get("MinecraftWinHeight").toInt()); + + QString lwjgl = QDir(m_lwjglFolderSetting->get().toString() + "/" + lwjglVersion()) + .absolutePath(); + launchScript += "userName " + account->player_name + "\n"; + launchScript += "sessionId " + account->session + "\n"; + launchScript += "windowTitle " + windowTitle() + "\n"; + launchScript += "windowParams " + windowParams + "\n"; + launchScript += "lwjgl " + lwjgl + "\n"; + launchScript += "launcher legacy\n"; + } + auto process = MinecraftProcess::create(std::dynamic_pointer_cast<MinecraftInstance>(getSharedPtr())); + process->setLaunchScript(launchScript); + process->setWorkdir(minecraftRoot()); + process->setLogin(account); + return process; +} + +void LegacyInstance::cleanupAfterRun() +{ + // FIXME: delete the launcher and icons and whatnot. +} + +std::shared_ptr<ModList> LegacyInstance::coreModList() const +{ + if (!core_mod_list) + { + core_mod_list.reset(new ModList(coreModsDir())); + } + core_mod_list->update(); + return core_mod_list; +} + +std::shared_ptr<ModList> LegacyInstance::jarModList() const +{ + if (!jar_mod_list) + { + auto list = new ModList(jarModsDir(), modListFile()); + connect(list, SIGNAL(changed()), SLOT(jarModsChanged())); + jar_mod_list.reset(list); + } + jar_mod_list->update(); + return jar_mod_list; +} + +QList<Mod> LegacyInstance::getJarMods() const +{ + return jarModList()->allMods(); +} + +void LegacyInstance::jarModsChanged() +{ + qDebug() << "Jar mods of instance " << name() << " have changed. Jar will be rebuilt."; + setShouldRebuild(true); +} + +std::shared_ptr<ModList> LegacyInstance::loaderModList() const +{ + if (!loader_mod_list) + { + loader_mod_list.reset(new ModList(loaderModsDir())); + } + loader_mod_list->update(); + return loader_mod_list; +} + +std::shared_ptr<ModList> LegacyInstance::texturePackList() const +{ + if (!texture_pack_list) + { + texture_pack_list.reset(new ModList(texturePacksDir())); + } + texture_pack_list->update(); + return texture_pack_list; +} + +QString LegacyInstance::jarModsDir() const +{ + return PathCombine(instanceRoot(), "instMods"); +} + +QString LegacyInstance::binDir() const +{ + return PathCombine(minecraftRoot(), "bin"); +} + +QString LegacyInstance::libDir() const +{ + return PathCombine(minecraftRoot(), "lib"); +} + +QString LegacyInstance::savesDir() const +{ + return PathCombine(minecraftRoot(), "saves"); +} + +QString LegacyInstance::loaderModsDir() const +{ + return PathCombine(minecraftRoot(), "mods"); +} + +QString LegacyInstance::coreModsDir() const +{ + return PathCombine(minecraftRoot(), "coremods"); +} + +QString LegacyInstance::resourceDir() const +{ + return PathCombine(minecraftRoot(), "resources"); +} +QString LegacyInstance::texturePacksDir() const +{ + return PathCombine(minecraftRoot(), "texturepacks"); +} + +QString LegacyInstance::runnableJar() const +{ + return PathCombine(binDir(), "minecraft.jar"); +} + +QString LegacyInstance::modListFile() const +{ + return PathCombine(instanceRoot(), "modlist"); +} + +QString LegacyInstance::instanceConfigFolder() const +{ + return PathCombine(minecraftRoot(), "config"); +} + +bool LegacyInstance::shouldRebuild() const +{ + return m_settings->get("NeedsRebuild").toBool(); +} + +void LegacyInstance::setShouldRebuild(bool val) +{ + m_settings->set("NeedsRebuild", val); +} + +QString LegacyInstance::currentVersionId() const +{ + return m_settings->get("JarVersion").toString(); +} + +QString LegacyInstance::lwjglVersion() const +{ + return m_settings->get("LwjglVersion").toString(); +} + +void LegacyInstance::setLWJGLVersion(QString val) +{ + m_settings->set("LwjglVersion", val); +} + +QString LegacyInstance::intendedVersionId() const +{ + return m_settings->get("IntendedJarVersion").toString(); +} + +bool LegacyInstance::setIntendedVersionId(QString version) +{ + settings().set("IntendedJarVersion", version); + setShouldUpdate(true); + return true; +} + +bool LegacyInstance::shouldUpdate() const +{ + QVariant var = settings().get("ShouldUpdate"); + if (!var.isValid() || var.toBool() == false) + { + return intendedVersionId() != currentVersionId(); + } + return true; +} + +void LegacyInstance::setShouldUpdate(bool val) +{ + settings().set("ShouldUpdate", val); +} + +QString LegacyInstance::defaultBaseJar() const +{ + return "versions/" + intendedVersionId() + "/" + intendedVersionId() + ".jar"; +} + +QString LegacyInstance::defaultCustomBaseJar() const +{ + return PathCombine(binDir(), "mcbackup.jar"); +} + +QString LegacyInstance::getStatusbarDescription() +{ + if (flags() & VersionBrokenFlag) + { + return tr("Legacy : %1 (broken)").arg(intendedVersionId()); + } + return tr("Legacy : %1").arg(intendedVersionId()); +} + +QString LegacyInstance::lwjglFolder() const +{ + return m_lwjglFolderSetting->get().toString(); +} diff --git a/logic/minecraft/LegacyInstance.h b/logic/minecraft/LegacyInstance.h new file mode 100644 index 00000000..353718c1 --- /dev/null +++ b/logic/minecraft/LegacyInstance.h @@ -0,0 +1,127 @@ +/* Copyright 2013-2015 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/minecraft/MinecraftInstance.h" +#include "gui/pages/BasePageProvider.h" + +class ModList; +class Task; + +class LegacyInstance : public MinecraftInstance, public BasePageProvider +{ + Q_OBJECT +public: + + explicit LegacyInstance(SettingsObjectPtr globalSettings, SettingsObjectPtr settings, const QString &rootDir); + + virtual void init() {}; + + /// Path to the instance's minecraft.jar + QString runnableJar() const; + + //! Path to the instance's modlist file. + QString modListFile() const; + + ////// Edit Instance Dialog stuff ////// + virtual QList<BasePage *> getPages(); + virtual QString dialogTitle(); + + ////// Mod Lists ////// + std::shared_ptr<ModList> jarModList() const ; + virtual QList< Mod > getJarMods() const override; + std::shared_ptr<ModList> coreModList() const; + std::shared_ptr<ModList> loaderModList() const; + std::shared_ptr<ModList> texturePackList() const override; + + ////// Directories ////// + QString libDir() const; + QString savesDir() const; + QString texturePacksDir() const; + QString jarModsDir() const; + QString binDir() const; + QString loaderModsDir() const; + QString coreModsDir() const; + 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 + * re-added to a fresh minecraft.jar file. + */ + bool shouldRebuild() const; + void setShouldRebuild(bool val); + + virtual QString currentVersionId() const override; + + //! The version of LWJGL that this instance uses. + QString lwjglVersion() const; + + //! Where the lwjgl versions foor this instance can be found... HACK HACK HACK + QString lwjglFolder() const; + + /// st the version of LWJGL libs this instance will use + void setLWJGLVersion(QString val); + + virtual QString intendedVersionId() const override; + virtual bool setIntendedVersionId(QString version) override; + + virtual QSet<QString> traits() + { + return {"legacy-instance", "texturepacks"}; + }; + + virtual bool shouldUpdate() const override; + virtual void setShouldUpdate(bool val) override; + virtual std::shared_ptr<Task> doUpdate() override; + + virtual BaseProcess *prepareForLaunch(AuthSessionPtr account) override; + virtual void cleanupAfterRun() override; + + virtual QString getStatusbarDescription() override; + +protected: + mutable std::shared_ptr<ModList> jar_mod_list; + mutable std::shared_ptr<ModList> core_mod_list; + mutable std::shared_ptr<ModList> loader_mod_list; + mutable std::shared_ptr<ModList> texture_pack_list; + std::shared_ptr<Setting> m_lwjglFolderSetting; +protected +slots: + virtual void jarModsChanged(); +}; diff --git a/logic/minecraft/LegacyUpdate.cpp b/logic/minecraft/LegacyUpdate.cpp new file mode 100644 index 00000000..d853536a --- /dev/null +++ b/logic/minecraft/LegacyUpdate.cpp @@ -0,0 +1,467 @@ +/* Copyright 2013-2015 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + |
