NOISSUE move files into paths that make more sense
This commit is contained in:
455
logic/minecraft/legacy/LegacyInstance.cpp
Normal file
455
logic/minecraft/legacy/LegacyInstance.cpp
Normal file
@ -0,0 +1,455 @@
|
||||
/* 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 <settings/Setting.h>
|
||||
|
||||
#include "LegacyInstance.h"
|
||||
|
||||
#include "minecraft/legacy/LegacyUpdate.h"
|
||||
#include "icons/IconList.h"
|
||||
#include "launch/LaunchTask.h"
|
||||
#include <launch/steps/LaunchMinecraft.h>
|
||||
#include <launch/steps/PostLaunchCommand.h>
|
||||
#include <launch/steps/ModMinecraftJar.h>
|
||||
#include <launch/steps/Update.h>
|
||||
#include <launch/steps/PreLaunchCommand.h>
|
||||
#include <launch/steps/TextPrint.h>
|
||||
#include <launch/steps/CheckJava.h>
|
||||
#include "minecraft/ModList.h"
|
||||
#include "minecraft/WorldList.h"
|
||||
#include <MMCZip.h>
|
||||
#include <FileSystem.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", "");
|
||||
}
|
||||
|
||||
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::createUpdateTask()
|
||||
{
|
||||
// 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));
|
||||
}
|
||||
|
||||
std::shared_ptr<LaunchTask> LegacyInstance::createLaunchTask(AuthSessionPtr session)
|
||||
{
|
||||
QString launchScript;
|
||||
QIcon icon = ENV.icons()->getIcon(iconKey());
|
||||
auto pixmap = icon.pixmap(128, 128);
|
||||
pixmap.save(FS::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 " + session->player_name + "\n";
|
||||
launchScript += "sessionId " + session->session + "\n";
|
||||
launchScript += "windowTitle " + windowTitle() + "\n";
|
||||
launchScript += "windowParams " + windowParams + "\n";
|
||||
launchScript += "lwjgl " + lwjgl + "\n";
|
||||
launchScript += "launcher legacy\n";
|
||||
}
|
||||
auto process = LaunchTask::create(std::dynamic_pointer_cast<MinecraftInstance>(getSharedPtr()));
|
||||
auto pptr = process.get();
|
||||
|
||||
// print a header
|
||||
{
|
||||
process->appendStep(std::make_shared<TextPrint>(pptr, "Minecraft folder is:\n" + minecraftRoot() + "\n\n", MessageLevel::MultiMC));
|
||||
}
|
||||
{
|
||||
auto step = std::make_shared<CheckJava>(pptr);
|
||||
process->appendStep(step);
|
||||
}
|
||||
// run pre-launch command if that's needed
|
||||
if(getPreLaunchCommand().size())
|
||||
{
|
||||
auto step = std::make_shared<PreLaunchCommand>(pptr);
|
||||
step->setWorkingDirectory(minecraftRoot());
|
||||
process->appendStep(step);
|
||||
}
|
||||
// if we aren't in offline mode,.
|
||||
if(session->status != AuthSession::PlayableOffline)
|
||||
{
|
||||
process->appendStep(std::make_shared<Update>(pptr));
|
||||
}
|
||||
// if there are any jar mods
|
||||
if(getJarMods().size())
|
||||
{
|
||||
auto step = std::make_shared<ModMinecraftJar>(pptr);
|
||||
process->appendStep(step);
|
||||
}
|
||||
// actually launch the game
|
||||
{
|
||||
auto step = std::make_shared<LaunchMinecraft>(pptr);
|
||||
step->setWorkingDirectory(minecraftRoot());
|
||||
step->setLaunchScript(launchScript);
|
||||
process->appendStep(step);
|
||||
}
|
||||
// run post-exit command if that's needed
|
||||
if(getPostExitCommand().size())
|
||||
{
|
||||
auto step = std::make_shared<PostLaunchCommand>(pptr);
|
||||
step->setWorkingDirectory(minecraftRoot());
|
||||
process->appendStep(step);
|
||||
}
|
||||
if (session)
|
||||
{
|
||||
process->setCensorFilter(createCensorFilterFromSession(session));
|
||||
}
|
||||
return process;
|
||||
}
|
||||
|
||||
std::shared_ptr<Task> LegacyInstance::createJarModdingTask()
|
||||
{
|
||||
class JarModTask : public Task
|
||||
{
|
||||
public:
|
||||
explicit JarModTask(std::shared_ptr<LegacyInstance> inst) : Task(nullptr), m_inst(inst)
|
||||
{
|
||||
}
|
||||
virtual void executeTask()
|
||||
{
|
||||
if (!m_inst->shouldRebuild())
|
||||
{
|
||||
emitSucceeded();
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the mod list
|
||||
auto modList = m_inst->getJarMods();
|
||||
|
||||
QFileInfo runnableJar(m_inst->runnableJar());
|
||||
QFileInfo baseJar(m_inst->baseJar());
|
||||
bool base_is_custom = m_inst->shouldUseCustomBaseJar();
|
||||
|
||||
// Nothing to do if there are no jar mods to install, no backup and just the mc jar
|
||||
if (base_is_custom)
|
||||
{
|
||||
// yes, this can happen if the instance only has the runnable jar and not the base jar
|
||||
// it *could* be assumed that such an instance is vanilla, but that wouldn't be safe
|
||||
// because that's not something mmc4 guarantees
|
||||
if (runnableJar.isFile() && !baseJar.exists() && modList.empty())
|
||||
{
|
||||
m_inst->setShouldRebuild(false);
|
||||
emitSucceeded();
|
||||
return;
|
||||
}
|
||||
|
||||
setStatus(tr("Installing mods: Backing up minecraft.jar ..."));
|
||||
if (!baseJar.exists() && !QFile::copy(runnableJar.filePath(), baseJar.filePath()))
|
||||
{
|
||||
emitFailed("It seems both the active and base jar are gone. A fresh base jar will "
|
||||
"be used on next run.");
|
||||
m_inst->setShouldRebuild(true);
|
||||
m_inst->setShouldUpdate(true);
|
||||
m_inst->setShouldUseCustomBaseJar(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!baseJar.exists())
|
||||
{
|
||||
emitFailed("The base jar " + baseJar.filePath() + " does not exist");
|
||||
return;
|
||||
}
|
||||
|
||||
if (runnableJar.exists() && !QFile::remove(runnableJar.filePath()))
|
||||
{
|
||||
emitFailed("Failed to delete old minecraft.jar");
|
||||
return;
|
||||
}
|
||||
|
||||
setStatus(tr("Installing mods: Opening minecraft.jar ..."));
|
||||
|
||||
QString outputJarPath = runnableJar.filePath();
|
||||
QString inputJarPath = baseJar.filePath();
|
||||
|
||||
if(!MMCZip::createModdedJar(inputJarPath, outputJarPath, modList))
|
||||
{
|
||||
emitFailed(tr("Failed to create the custom Minecraft jar file."));
|
||||
return;
|
||||
}
|
||||
m_inst->setShouldRebuild(false);
|
||||
// inst->UpdateVersion(true);
|
||||
emitSucceeded();
|
||||
return;
|
||||
|
||||
}
|
||||
std::shared_ptr<LegacyInstance> m_inst;
|
||||
};
|
||||
return std::make_shared<JarModTask>(std::dynamic_pointer_cast<LegacyInstance>(shared_from_this()));
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
std::shared_ptr<WorldList> LegacyInstance::worldList() const
|
||||
{
|
||||
if (!m_world_list)
|
||||
{
|
||||
m_world_list.reset(new WorldList(savesDir()));
|
||||
}
|
||||
return m_world_list;
|
||||
}
|
||||
|
||||
QString LegacyInstance::jarModsDir() const
|
||||
{
|
||||
return FS::PathCombine(instanceRoot(), "instMods");
|
||||
}
|
||||
|
||||
QString LegacyInstance::binDir() const
|
||||
{
|
||||
return FS::PathCombine(minecraftRoot(), "bin");
|
||||
}
|
||||
|
||||
QString LegacyInstance::libDir() const
|
||||
{
|
||||
return FS::PathCombine(minecraftRoot(), "lib");
|
||||
}
|
||||
|
||||
QString LegacyInstance::savesDir() const
|
||||
{
|
||||
return FS::PathCombine(minecraftRoot(), "saves");
|
||||
}
|
||||
|
||||
QString LegacyInstance::loaderModsDir() const
|
||||
{
|
||||
return FS::PathCombine(minecraftRoot(), "mods");
|
||||
}
|
||||
|
||||
QString LegacyInstance::coreModsDir() const
|
||||
{
|
||||
return FS::PathCombine(minecraftRoot(), "coremods");
|
||||
}
|
||||
|
||||
QString LegacyInstance::resourceDir() const
|
||||
{
|
||||
return FS::PathCombine(minecraftRoot(), "resources");
|
||||
}
|
||||
QString LegacyInstance::texturePacksDir() const
|
||||
{
|
||||
return FS::PathCombine(minecraftRoot(), "texturepacks");
|
||||
}
|
||||
|
||||
QString LegacyInstance::runnableJar() const
|
||||
{
|
||||
return FS::PathCombine(binDir(), "minecraft.jar");
|
||||
}
|
||||
|
||||
QString LegacyInstance::modListFile() const
|
||||
{
|
||||
return FS::PathCombine(instanceRoot(), "modlist");
|
||||
}
|
||||
|
||||
QString LegacyInstance::instanceConfigFolder() const
|
||||
{
|
||||
return FS::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 FS::PathCombine(binDir(), "mcbackup.jar");
|
||||
}
|
||||
|
||||
QString LegacyInstance::lwjglFolder() const
|
||||
{
|
||||
return m_lwjglFolderSetting->get().toString();
|
||||
}
|
||||
|
||||
QString LegacyInstance::typeName() const
|
||||
{
|
||||
return tr("Legacy");
|
||||
}
|
135
logic/minecraft/legacy/LegacyInstance.h
Normal file
135
logic/minecraft/legacy/LegacyInstance.h
Normal file
@ -0,0 +1,135 @@
|
||||
/* 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 "minecraft/MinecraftInstance.h"
|
||||
|
||||
#include "multimc_logic_export.h"
|
||||
|
||||
class ModList;
|
||||
class Task;
|
||||
|
||||
class MULTIMC_LOGIC_EXPORT LegacyInstance : public MinecraftInstance
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
explicit LegacyInstance(SettingsObjectPtr globalSettings, SettingsObjectPtr settings, const QString &rootDir);
|
||||
|
||||
virtual void init() override {};
|
||||
|
||||
/// 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;
|
||||
std::shared_ptr<WorldList> worldList() 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() override
|
||||
{
|
||||
return {"legacy-instance", "texturepacks"};
|
||||
};
|
||||
|
||||
virtual bool shouldUpdate() const override;
|
||||
virtual void setShouldUpdate(bool val) override;
|
||||
virtual std::shared_ptr<Task> createUpdateTask() override;
|
||||
|
||||
virtual std::shared_ptr<LaunchTask> createLaunchTask(AuthSessionPtr account) override;
|
||||
|
||||
virtual std::shared_ptr<Task> createJarModdingTask() override;
|
||||
|
||||
virtual void cleanupAfterRun() override;
|
||||
|
||||
virtual QString typeName() const 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;
|
||||
mutable std::shared_ptr<WorldList> m_world_list;
|
||||
std::shared_ptr<Setting> m_lwjglFolderSetting;
|
||||
protected
|
||||
slots:
|
||||
virtual void jarModsChanged();
|
||||
};
|
395
logic/minecraft/legacy/LegacyUpdate.cpp
Normal file
395
logic/minecraft/legacy/LegacyUpdate.cpp
Normal file
@ -0,0 +1,395 @@
|
||||
/* 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 <QStringList>
|
||||
#include <quazip.h>
|
||||
#include <quazipfile.h>
|
||||
#include <QDebug>
|
||||
|
||||
#include "Env.h"
|
||||
#include "BaseInstance.h"
|
||||
#include "net/URLConstants.h"
|
||||
#include "MMCZip.h"
|
||||
|
||||
#include "LegacyUpdate.h"
|
||||
|
||||
#include "LwjglVersionList.h"
|
||||
#include "minecraft/MinecraftVersionList.h"
|
||||
#include "minecraft/ModList.h"
|
||||
#include "LegacyInstance.h"
|
||||
#include <FileSystem.h>
|
||||
|
||||
LegacyUpdate::LegacyUpdate(BaseInstance *inst, QObject *parent) : Task(parent), m_inst(inst)
|
||||
{
|
||||
}
|
||||
|
||||
void LegacyUpdate::executeTask()
|
||||
{
|
||||
fmllibsStart();
|
||||
}
|
||||
|
||||
void LegacyUpdate::fmllibsStart()
|
||||
{
|
||||
// Get the mod list
|
||||
LegacyInstance *inst = (LegacyInstance *)m_inst;
|
||||
auto modList = inst->jarModList();
|
||||
|
||||
bool forge_present = false;
|
||||
|
||||
QString version = inst->intendedVersionId();
|
||||
auto & fmlLibsMapping = g_VersionFilterData.fmlLibsMapping;
|
||||
if (!fmlLibsMapping.contains(version))
|
||||
{
|
||||
lwjglStart();
|
||||
return;
|
||||
}
|
||||
|
||||
auto &libList = fmlLibsMapping[version];
|
||||
|
||||
// determine if we need some libs for FML or forge
|
||||
setStatus(tr("Checking for FML libraries..."));
|
||||
for (unsigned i = 0; i < modList->size(); i++)
|
||||
{
|
||||
auto &mod = modList->operator[](i);
|
||||
|
||||
// do not use disabled mods.
|
||||
if (!mod.enabled())
|
||||
continue;
|
||||
|
||||
if (mod.type() != Mod::MOD_ZIPFILE)
|
||||
continue;
|
||||
|
||||
if (mod.mmc_id().contains("forge", Qt::CaseInsensitive))
|
||||
{
|
||||
forge_present = true;
|
||||
break;
|
||||
}
|
||||
if (mod.mmc_id().contains("fml", Qt::CaseInsensitive))
|
||||
{
|
||||
forge_present = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// we don't...
|
||||
if (!forge_present)
|
||||
{
|
||||
lwjglStart();
|
||||
return;
|
||||
}
|
||||
|
||||
// now check the lib folder inside the instance for files.
|
||||
for (auto &lib : libList)
|
||||
{
|
||||
QFileInfo libInfo(FS::PathCombine(inst->libDir(), lib.filename));
|
||||
if (libInfo.exists())
|
||||
continue;
|
||||
fmlLibsToProcess.append(lib);
|
||||
}
|
||||
|
||||
// if everything is in place, there's nothing to do here...
|
||||
if (fmlLibsToProcess.isEmpty())
|
||||
{
|
||||
lwjglStart();
|
||||
return;
|
||||
}
|
||||
|
||||
// download missing libs to our place
|
||||
setStatus(tr("Dowloading FML libraries..."));
|
||||
auto dljob = new NetJob("FML libraries");
|
||||
auto metacache = ENV.metacache();
|
||||
for (auto &lib : fmlLibsToProcess)
|
||||
{
|
||||
auto entry = metacache->resolveEntry("fmllibs", lib.filename);
|
||||
QString urlString = lib.ours ? URLConstants::FMLLIBS_OUR_BASE_URL + lib.filename
|
||||
: URLConstants::FMLLIBS_FORGE_BASE_URL + lib.filename;
|
||||
dljob->addNetAction(CacheDownload::make(QUrl(urlString), entry));
|
||||
}
|
||||
|
||||
connect(dljob, &NetJob::succeeded, this, &LegacyUpdate::fmllibsFinished);
|
||||
connect(dljob, &NetJob::failed, this, &LegacyUpdate::fmllibsFailed);
|
||||
connect(dljob, &NetJob::progress, this, &LegacyUpdate::progress);
|
||||
legacyDownloadJob.reset(dljob);
|
||||
legacyDownloadJob->start();
|
||||
}
|
||||
|
||||
void LegacyUpdate::fmllibsFinished()
|
||||
{
|
||||
legacyDownloadJob.reset();
|
||||
if(!fmlLibsToProcess.isEmpty())
|
||||
{
|
||||
setStatus(tr("Copying FML libraries into the instance..."));
|
||||
LegacyInstance *inst = (LegacyInstance *)m_inst;
|
||||
auto metacache = ENV.metacache();
|
||||
int index = 0;
|
||||
for (auto &lib : fmlLibsToProcess)
|
||||
{
|
||||
progress(index, fmlLibsToProcess.size());
|
||||
auto entry = metacache->resolveEntry("fmllibs", lib.filename);
|
||||
auto path = FS::PathCombine(inst->libDir(), lib.filename);
|
||||
if(!FS::ensureFilePathExists(path))
|
||||
{
|
||||
emitFailed(tr("Failed creating FML library folder inside the instance."));
|
||||
return;
|
||||
}
|
||||
if (!QFile::copy(entry->getFullPath(), FS::PathCombine(inst->libDir(), lib.filename)))
|
||||
{
|
||||
emitFailed(tr("Failed copying Forge/FML library: %1.").arg(lib.filename));
|
||||
return;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
progress(index, fmlLibsToProcess.size());
|
||||
}
|
||||
lwjglStart();
|
||||
}
|
||||
|
||||
void LegacyUpdate::fmllibsFailed(QString reason)
|
||||
{
|
||||
emitFailed(tr("Game update failed: it was impossible to fetch the required FML libraries. Reason: %1").arg(reason));
|
||||
return;
|
||||
}
|
||||
|
||||
void LegacyUpdate::lwjglStart()
|
||||
{
|
||||
LegacyInstance *inst = (LegacyInstance *)m_inst;
|
||||
|
||||
lwjglVersion = inst->lwjglVersion();
|
||||
lwjglTargetPath = FS::PathCombine(inst->lwjglFolder(), lwjglVersion);
|
||||
lwjglNativesPath = FS::PathCombine(lwjglTargetPath, "natives");
|
||||
|
||||
// if the 'done' file exists, we don't have to download this again
|
||||
QFileInfo doneFile(FS::PathCombine(lwjglTargetPath, "done"));
|
||||
if (doneFile.exists())
|
||||
{
|
||||
jarStart();
|
||||
return;
|
||||
}
|
||||
|
||||
auto list = std::dynamic_pointer_cast<LWJGLVersionList>(ENV.getVersionList("org.lwjgl.legacy"));
|
||||
if (!list->isLoaded())
|
||||
{
|
||||
emitFailed("Too soon! Let the LWJGL list load :)");
|
||||
return;
|
||||
}
|
||||
|
||||
setStatus(tr("Downloading new LWJGL..."));
|
||||
auto version = std::dynamic_pointer_cast<LWJGLVersion>(list->findVersion(lwjglVersion));
|
||||
if (!version)
|
||||
{
|
||||
emitFailed("Game update failed: the selected LWJGL version is invalid.");
|
||||
return;
|
||||
}
|
||||
|
||||
QString url = version->url();
|
||||
QUrl realUrl(url);
|
||||
QString hostname = realUrl.host();
|
||||
auto worker = ENV.qnam();
|
||||
QNetworkRequest req(realUrl);
|
||||
req.setRawHeader("Host", hostname.toLatin1());
|
||||
req.setHeader(QNetworkRequest::UserAgentHeader, "MultiMC/5.0 (Cached)");
|
||||
QNetworkReply *rep = worker->get(req);
|
||||
|
||||
m_reply = std::shared_ptr<QNetworkReply>(rep);
|
||||
connect(rep, &QNetworkReply::downloadProgress, this, &LegacyUpdate::progress);
|
||||
connect(worker.get(), &QNetworkAccessManager::finished, this, &LegacyUpdate::lwjglFinished);
|
||||
}
|
||||
|
||||
void LegacyUpdate::lwjglFinished(QNetworkReply *reply)
|
||||
{
|
||||
if (m_reply.get() != reply)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (reply->error() != QNetworkReply::NoError)
|
||||
{
|
||||
emitFailed("Failed to download: " + reply->errorString() +
|
||||
"\nSometimes you have to wait a bit if you download many LWJGL versions in "
|
||||
"a row. YMMV");
|
||||
return;
|
||||
}
|
||||
auto worker = ENV.qnam();
|
||||
// Here i check if there is a cookie for me in the reply and extract it
|
||||
QList<QNetworkCookie> cookies =
|
||||
qvariant_cast<QList<QNetworkCookie>>(reply->header(QNetworkRequest::SetCookieHeader));
|
||||
if (cookies.count() != 0)
|
||||
{
|
||||
// you must tell which cookie goes with which url
|
||||
worker->cookieJar()->setCookiesFromUrl(cookies, QUrl("sourceforge.net"));
|
||||
}
|
||||
|
||||
// here you can check for the 302 or whatever other header i need
|
||||
QVariant newLoc = reply->header(QNetworkRequest::LocationHeader);
|
||||
if (newLoc.isValid())
|
||||
{
|
||||
QString redirectedTo = reply->header(QNetworkRequest::LocationHeader).toString();
|
||||
QUrl realUrl(redirectedTo);
|
||||
QString hostname = realUrl.host();
|
||||
QNetworkRequest req(redirectedTo);
|
||||
req.setRawHeader("Host", hostname.toLatin1());
|
||||
req.setHeader(QNetworkRequest::UserAgentHeader, "MultiMC/5.0 (Cached)");
|
||||
QNetworkReply *rep = worker->get(req);
|
||||
connect(rep, &QNetworkReply::downloadProgress, this, &LegacyUpdate::progress);
|
||||
m_reply = std::shared_ptr<QNetworkReply>(rep);
|
||||
return;
|
||||
}
|
||||
QFile saveMe("lwjgl.zip");
|
||||
saveMe.open(QIODevice::WriteOnly);
|
||||
saveMe.write(m_reply->readAll());
|
||||
saveMe.close();
|
||||
setStatus(tr("Installing new LWJGL..."));
|
||||
extractLwjgl();
|
||||
jarStart();
|
||||
}
|
||||
void LegacyUpdate::extractLwjgl()
|
||||
{
|
||||
// make sure the directories are there
|
||||
|
||||
bool success = FS::ensureFolderPathExists(lwjglNativesPath);
|
||||
|
||||
if (!success)
|
||||
{
|
||||
emitFailed("Failed to extract the lwjgl libs - error when creating required folders.");
|
||||
return;
|
||||
}
|
||||
|
||||
QuaZip zip("lwjgl.zip");
|
||||
if (!zip.open(QuaZip::mdUnzip))
|
||||
{
|
||||
emitFailed("Failed to extract the lwjgl libs - not a valid archive.");
|
||||
return;
|
||||
}
|
||||
|
||||
// and now we are going to access files inside it
|
||||
QuaZipFile file(&zip);
|
||||
const QString jarNames[] = {"jinput.jar", "lwjgl_util.jar", "lwjgl.jar"};
|
||||
for (bool more = zip.goToFirstFile(); more; more = zip.goToNextFile())
|
||||
{
|
||||
if (!file.open(QIODevice::ReadOnly))
|
||||
{
|
||||
zip.close();
|
||||
emitFailed("Failed to extract the lwjgl libs - error while reading archive.");
|
||||
return;
|
||||
}
|
||||
QuaZipFileInfo info;
|
||||
QString name = file.getActualFileName();
|
||||
if (name.endsWith('/'))
|
||||
{
|
||||
file.close();
|
||||
continue;
|
||||
}
|
||||
QString destFileName;
|
||||
// Look for the jars
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
if (name.endsWith(jarNames[i]))
|
||||
{
|
||||
destFileName = FS::PathCombine(lwjglTargetPath, jarNames[i]);
|
||||
}
|
||||
}
|
||||
// Not found? look for the natives
|
||||
if (destFileName.isEmpty())
|
||||
{
|
||||
#ifdef Q_OS_WIN32
|
||||
QString nativesDir = "windows";
|
||||
#else
|
||||
#ifdef Q_OS_MAC
|
||||
QString nativesDir = "macosx";
|
||||
#else
|
||||
QString nativesDir = "linux";
|
||||
#endif
|
||||
#endif
|
||||
if (name.contains(nativesDir))
|
||||
{
|
||||
int lastSlash = name.lastIndexOf('/');
|
||||
int lastBackSlash = name.lastIndexOf('\\');
|
||||
if (lastSlash != -1)
|
||||
name = name.mid(lastSlash + 1);
|
||||
else if (lastBackSlash != -1)
|
||||
name = name.mid(lastBackSlash + 1);
|
||||
destFileName = FS::PathCombine(lwjglNativesPath, name);
|
||||
}
|
||||
}
|
||||
// Now if destFileName is still empty, go to the next file.
|
||||
if (!destFileName.isEmpty())
|
||||
{
|
||||
setStatus(tr("Installing new LWJGL - extracting ") + name + "...");
|
||||
QFile output(destFileName);
|
||||
output.open(QIODevice::WriteOnly);
|
||||
output.write(file.readAll());
|
||||
output.close();
|
||||
}
|
||||
file.close(); // do not forget to close!
|
||||
}
|
||||
zip.close();
|
||||
m_reply.reset();
|
||||
QFile doneFile(FS::PathCombine(lwjglTargetPath, "done"));
|
||||
doneFile.open(QIODevice::WriteOnly);
|
||||
doneFile.write("done.");
|
||||
doneFile.close();
|
||||
}
|
||||
|
||||
void LegacyUpdate::lwjglFailed(QString reason)
|
||||
{
|
||||
emitFailed(tr("Bad stuff happened while trying to get the lwjgl libs: %1").arg(reason));
|
||||
}
|
||||
|
||||
void LegacyUpdate::jarStart()
|
||||
{
|
||||
LegacyInstance *inst = (LegacyInstance *)m_inst;
|
||||
if (!inst->shouldUpdate() || inst->shouldUseCustomBaseJar())
|
||||
{
|
||||
emitSucceeded();
|
||||
return;
|
||||
}
|
||||
|
||||
setStatus(tr("Checking for jar updates..."));
|
||||
// Make directories
|
||||
QDir binDir(inst->binDir());
|
||||
if (!binDir.exists() && !binDir.mkpath("."))
|
||||
{
|
||||
emitFailed("Failed to create bin folder.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Build a list of URLs that will need to be downloaded.
|
||||
setStatus(tr("Downloading new minecraft.jar ..."));
|
||||
|
||||
QString version_id = inst->intendedVersionId();
|
||||
QString localPath = version_id + "/" + version_id + ".jar";
|
||||
QString urlstr = "http://" + URLConstants::AWS_DOWNLOAD_VERSIONS + localPath;
|
||||
|
||||
auto dljob = new NetJob("Minecraft.jar for version " + version_id);
|
||||
|
||||
auto metacache = ENV.metacache();
|
||||
auto entry = metacache->resolveEntry("versions", localPath);
|
||||
dljob->addNetAction(CacheDownload::make(QUrl(urlstr), entry));
|
||||
connect(dljob, SIGNAL(succeeded()), SLOT(jarFinished()));
|
||||
connect(dljob, SIGNAL(failed(QString)), SLOT(jarFailed(QString)));
|
||||
connect(dljob, SIGNAL(progress(qint64, qint64)), SIGNAL(progress(qint64, qint64)));
|
||||
legacyDownloadJob.reset(dljob);
|
||||
legacyDownloadJob->start();
|
||||
}
|
||||
|
||||
void LegacyUpdate::jarFinished()
|
||||
{
|
||||
// process the jar
|
||||
emitSucceeded();
|
||||
}
|
||||
|
||||
void LegacyUpdate::jarFailed(QString reason)
|
||||
{
|
||||
// bad, bad
|
||||
emitFailed(tr("Failed to download the minecraft jar: %1.").arg(reason));
|
||||
}
|
70
logic/minecraft/legacy/LegacyUpdate.h
Normal file
70
logic/minecraft/legacy/LegacyUpdate.h
Normal file
@ -0,0 +1,70 @@
|
||||
/* 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 <QObject>
|
||||
#include <QList>
|
||||
#include <QUrl>
|
||||
|
||||
#include "net/NetJob.h"
|
||||
#include "tasks/Task.h"
|
||||
#include "minecraft/VersionFilterData.h"
|
||||
|
||||
class MinecraftVersion;
|
||||
class BaseInstance;
|
||||
class QuaZip;
|
||||
class Mod;
|
||||
|
||||
class LegacyUpdate : public Task
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit LegacyUpdate(BaseInstance *inst, QObject *parent = 0);
|
||||
virtual void executeTask();
|
||||
|
||||
private
|
||||
slots:
|
||||
void lwjglStart();
|
||||
void lwjglFinished(QNetworkReply *);
|
||||
void lwjglFailed(QString reason);
|
||||
|
||||
void jarStart();
|
||||
void jarFinished();
|
||||
void jarFailed(QString reason);
|
||||
|
||||
void fmllibsStart();
|
||||
void fmllibsFinished();
|
||||
void fmllibsFailed(QString reason);
|
||||
|
||||
void extractLwjgl();
|
||||
|
||||
private:
|
||||
|
||||
std::shared_ptr<QNetworkReply> m_reply;
|
||||
|
||||
// target version, determined during this task
|
||||
// MinecraftVersion *targetVersion;
|
||||
QString lwjglURL;
|
||||
QString lwjglVersion;
|
||||
|
||||
QString lwjglTargetPath;
|
||||
QString lwjglNativesPath;
|
||||
|
||||
private:
|
||||
NetJobPtr legacyDownloadJob;
|
||||
BaseInstance *m_inst = nullptr;
|
||||
QList<FMLlib> fmlLibsToProcess;
|
||||
};
|
189
logic/minecraft/legacy/LwjglVersionList.cpp
Normal file
189
logic/minecraft/legacy/LwjglVersionList.cpp
Normal file
@ -0,0 +1,189 @@
|
||||
/* 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 "LwjglVersionList.h"
|
||||
#include "Env.h"
|
||||
|
||||
#include <QtNetwork>
|
||||
#include <QtXml>
|
||||
#include <QRegExp>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#define RSS_URL "http://sourceforge.net/projects/java-game-lib/rss"
|
||||
|
||||
LWJGLVersionList::LWJGLVersionList(QObject *parent) : BaseVersionList(parent)
|
||||
{
|
||||
setLoading(false);
|
||||
}
|
||||
|
||||
QVariant LWJGLVersionList::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return QVariant();
|
||||
|
||||
if (index.row() > count())
|
||||
return QVariant();
|
||||
|
||||
const PtrLWJGLVersion version = m_vlist.at(index.row());
|
||||
|
||||
switch (role)
|
||||
{
|
||||
case Qt::DisplayRole:
|
||||
return version->name();
|
||||
|
||||
case Qt::ToolTipRole:
|
||||
return version->url();
|
||||
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
|
||||
QVariant LWJGLVersionList::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
switch (role)
|
||||
{
|
||||
case Qt::DisplayRole:
|
||||
return tr("Version");
|
||||
|
||||
case Qt::ToolTipRole:
|
||||
return tr("LWJGL version name.");
|
||||
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
|
||||
int LWJGLVersionList::columnCount(const QModelIndex &parent) const
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool LWJGLVersionList::isLoading() const
|
||||
{
|
||||
return m_loading;
|
||||
}
|
||||
|
||||
void LWJGLVersionList::loadList()
|
||||
{
|
||||
Q_ASSERT_X(!m_loading, "loadList", "list is already loading (m_loading is true)");
|
||||
|
||||
setLoading(true);
|
||||
auto worker = ENV.qnam();
|
||||
QNetworkRequest req(QUrl(RSS_URL));
|
||||
req.setRawHeader("Accept", "application/rss+xml, text/xml, */*");
|
||||
req.setRawHeader("User-Agent", "MultiMC/5.0 (Uncached)");
|
||||
reply = worker->get(req);
|
||||
connect(reply, SIGNAL(finished()), SLOT(netRequestComplete()));
|
||||
}
|
||||
|
||||
inline QDomElement getDomElementByTagName(QDomElement parent, QString tagname)
|
||||
{
|
||||
QDomNodeList elementList = parent.elementsByTagName(tagname);
|
||||
if (elementList.count())
|
||||
return elementList.at(0).toElement();
|
||||
else
|
||||
return QDomElement();
|
||||
}
|
||||
|
||||
void LWJGLVersionList::netRequestComplete()
|
||||
{
|
||||
if (reply->error() == QNetworkReply::NoError)
|
||||
{
|
||||
QRegExp lwjglRegex("lwjgl-(([0-9]\\.?)+)\\.zip");
|
||||
Q_ASSERT_X(lwjglRegex.isValid(), "load LWJGL list", "LWJGL regex is invalid");
|
||||
|
||||
QDomDocument doc;
|
||||
|
||||
QString xmlErrorMsg;
|
||||
int errorLine;
|
||||
auto rawData = reply->readAll();
|
||||
if (!doc.setContent(rawData, false, &xmlErrorMsg, &errorLine))
|
||||
{
|
||||
failed("Failed to load LWJGL list. XML error: " + xmlErrorMsg + " at line " +
|
||||
QString::number(errorLine));
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
QDomNodeList items = doc.elementsByTagName("item");
|
||||
|
||||
QList<PtrLWJGLVersion> tempList;
|
||||
|
||||
for (int i = 0; i < items.length(); i++)
|
||||
{
|
||||
Q_ASSERT_X(items.at(i).isElement(), "load LWJGL list",
|
||||
"XML element isn't an element... wat?");
|
||||
|
||||
QDomElement linkElement = getDomElementByTagName(items.at(i).toElement(), "link");
|
||||
if (linkElement.isNull())
|
||||
{
|
||||
qDebug() << "Link element" << i << "in RSS feed doesn't exist! Skipping.";
|
||||
continue;
|
||||
}
|
||||
|
||||
QString link = linkElement.text();
|
||||
|
||||
// Make sure it's a download link.
|
||||
if (link.endsWith("/download") && link.contains(lwjglRegex))
|
||||
{
|
||||
QString name = link.mid(lwjglRegex.indexIn(link) + 6);
|
||||
// Subtract 4 here to remove the .zip file extension.
|
||||
name = name.left(lwjglRegex.matchedLength() - 10);
|
||||
|
||||
QUrl url(link);
|
||||
if (!url.isValid())
|
||||
{
|
||||
qWarning() << "LWJGL version URL isn't valid:" << link << "Skipping.";
|
||||
continue;
|
||||
}
|
||||
qDebug() << "Discovered LWGL version" << name << "at" << link;
|
||||
tempList.append(std::make_shared<LWJGLVersion>(name, link));
|
||||
}
|
||||
}
|
||||
|
||||
beginResetModel();
|
||||
m_vlist.swap(tempList);
|
||||
endResetModel();
|
||||
|
||||
qDebug() << "Loaded LWJGL list.";
|
||||
finished();
|
||||
}
|
||||
else
|
||||
{
|
||||
failed("Failed to load LWJGL list. Network error: " + reply->errorString());
|
||||
}
|
||||
|
||||
setLoading(false);
|
||||
reply->deleteLater();
|
||||
}
|
||||
|
||||
void LWJGLVersionList::failed(QString msg)
|
||||
{
|
||||
qCritical() << msg;
|
||||
emit loadListFailed(msg);
|
||||
}
|
||||
|
||||
void LWJGLVersionList::finished()
|
||||
{
|
||||
emit loadListFinished();
|
||||
}
|
||||
|
||||
void LWJGLVersionList::setLoading(bool loading)
|
||||
{
|
||||
m_loading = loading;
|
||||
emit loadingStateUpdated(m_loading);
|
||||
}
|
156
logic/minecraft/legacy/LwjglVersionList.h
Normal file
156
logic/minecraft/legacy/LwjglVersionList.h
Normal file
@ -0,0 +1,156 @@
|
||||
/* 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 <QObject>
|
||||
#include <QAbstractListModel>
|
||||
#include <QUrl>
|
||||
#include <QNetworkReply>
|
||||
#include <memory>
|
||||
|
||||
#include "BaseVersion.h"
|
||||
#include "BaseVersionList.h"
|
||||
|
||||
#include "multimc_logic_export.h"
|
||||
|
||||
class LWJGLVersion;
|
||||
typedef std::shared_ptr<LWJGLVersion> PtrLWJGLVersion;
|
||||
|
||||
class MULTIMC_LOGIC_EXPORT LWJGLVersion : public BaseVersion
|
||||
{
|
||||
public:
|
||||
LWJGLVersion(const QString &name, const QString &url)
|
||||
: m_name(name), m_url(url)
|
||||
{
|
||||
}
|
||||
|
||||
virtual QString descriptor()
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
virtual QString name()
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
virtual QString typeString() const
|
||||
{
|
||||
return QObject::tr("Upstream");
|
||||
}
|
||||
|
||||
QString url() const
|
||||
{
|
||||
return m_url;
|
||||
}
|
||||
|
||||
protected:
|
||||
QString m_name;
|
||||
QString m_url;
|
||||
};
|
||||
|
||||
class MULTIMC_LOGIC_EXPORT LWJGLVersionList : public BaseVersionList
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit LWJGLVersionList(QObject *parent = 0);
|
||||
|
||||
bool isLoaded() override
|
||||
{
|
||||
return m_vlist.length() > 0;
|
||||
}
|
||||
virtual const BaseVersionPtr at(int i) const override
|
||||
{
|
||||
return m_vlist[i];
|
||||
}
|
||||
|
||||
virtual Task* getLoadTask() override
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
virtual void sortVersions() override {};
|
||||
|
||||
virtual void updateListData(QList< BaseVersionPtr > versions) override {};
|
||||
|
||||
int count() const override
|
||||
{
|
||||
return m_vlist.length();
|
||||
}
|
||||
|
||||
virtual QVariant data(const QModelIndex &index, int role) const override;
|
||||
virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
|
||||
virtual int rowCount(const QModelIndex &parent) const override
|
||||
{
|
||||
return count();
|
||||
}
|
||||
virtual int columnCount(const QModelIndex &parent) const override;
|
||||
|
||||
virtual bool isLoading() const;
|
||||
virtual bool errored() const
|
||||
{
|
||||
return m_errored;
|
||||
}
|
||||
|
||||
virtual QString lastErrorMsg() const
|
||||
{
|
||||
return m_lastErrorMsg;
|
||||
}
|
||||
|
||||
public
|
||||
slots:
|
||||
/*!
|
||||
* Loads the version list.
|
||||
* This is done asynchronously. On success, the loadListFinished() signal will
|
||||
* be emitted. The list model will be reset as well, resulting in the modelReset()
|
||||
* signal being emitted. Note that the model will be reset before loadListFinished() is
|
||||
* emitted.
|
||||
* If loading the list failed, the loadListFailed(QString msg),
|
||||
* signal will be emitted.
|
||||
*/
|
||||
virtual void loadList();
|
||||
|
||||
signals:
|
||||
/*!
|
||||
* Emitted when the list either starts or finishes loading.
|
||||
* \param loading Whether or not the list is loading.
|
||||
*/
|
||||
void loadingStateUpdated(bool loading);
|
||||
|
||||
void loadListFinished();
|
||||
|
||||
void loadListFailed(QString msg);
|
||||
|
||||
private:
|
||||
QList<PtrLWJGLVersion> m_vlist;
|
||||
|
||||
QNetworkReply *m_netReply;
|
||||
QNetworkReply *reply;
|
||||
|
||||
bool m_loading;
|
||||
bool m_errored;
|
||||
QString m_lastErrorMsg;
|
||||
|
||||
void failed(QString msg);
|
||||
|
||||
void finished();
|
||||
|
||||
void setLoading(bool loading);
|
||||
|
||||
private
|
||||
slots:
|
||||
virtual void netRequestComplete();
|
||||
};
|
Reference in New Issue
Block a user