Forge works now too, and so does forge+liteloader

This commit is contained in:
Jan Dalheimer 2014-01-23 21:31:41 +01:00
parent c39d26f445
commit 156bc8f276
13 changed files with 245 additions and 81 deletions

View File

@ -416,6 +416,8 @@ logic/DerpRule.h
logic/DerpRule.cpp logic/DerpRule.cpp
logic/OpSys.h logic/OpSys.h
logic/OpSys.cpp logic/OpSys.cpp
logic/BaseInstaller.h
logic/BaseInstaller.cpp
logic/ForgeInstaller.h logic/ForgeInstaller.h
logic/ForgeInstaller.cpp logic/ForgeInstaller.cpp
logic/LiteLoaderInstaller.h logic/LiteLoaderInstaller.h

View File

@ -55,7 +55,6 @@ DerpModEditDialog::DerpModEditDialog(DerpInstance *inst, QWidget *parent)
main_model->setSourceModel(m_version.get()); main_model->setSourceModel(m_version.get());
ui->libraryTreeView->setModel(main_model); ui->libraryTreeView->setModel(main_model);
ui->libraryTreeView->installEventFilter(this); ui->libraryTreeView->installEventFilter(this);
ui->mainClassEdit->setText(m_version->mainClass);
updateVersionControls(); updateVersionControls();
} }
else else
@ -98,6 +97,7 @@ void DerpModEditDialog::updateVersionControls()
ui->forgeBtn->setEnabled(true); ui->forgeBtn->setEnabled(true);
ui->liteloaderBtn->setEnabled(LiteLoaderInstaller().canApply(m_inst)); ui->liteloaderBtn->setEnabled(LiteLoaderInstaller().canApply(m_inst));
ui->customEditorBtn->setEnabled(customVersion); ui->customEditorBtn->setEnabled(customVersion);
ui->mainClassEdit->setText(m_version->mainClass);
} }
void DerpModEditDialog::disableVersionControls() void DerpModEditDialog::disableVersionControls()
@ -105,6 +105,7 @@ void DerpModEditDialog::disableVersionControls()
ui->forgeBtn->setEnabled(false); ui->forgeBtn->setEnabled(false);
ui->liteloaderBtn->setEnabled(false); ui->liteloaderBtn->setEnabled(false);
ui->customEditorBtn->setEnabled(false); ui->customEditorBtn->setEnabled(false);
ui->mainClassEdit->setText("");
} }
void DerpModEditDialog::on_customEditorBtn_clicked() void DerpModEditDialog::on_customEditorBtn_clicked()
@ -140,9 +141,9 @@ void DerpModEditDialog::on_forgeBtn_clicked()
// install // install
QString forgePath = entry->getFullPath(); QString forgePath = entry->getFullPath();
ForgeInstaller forge(forgePath, forgeVersion->universal_url); ForgeInstaller forge(forgePath, forgeVersion->universal_url);
if (!forge.apply(m_version)) if (!forge.add(m_inst))
{ {
// failure notice QLOG_ERROR() << "Failure installing forge";
} }
} }
else else
@ -155,12 +156,13 @@ void DerpModEditDialog::on_forgeBtn_clicked()
// install // install
QString forgePath = entry->getFullPath(); QString forgePath = entry->getFullPath();
ForgeInstaller forge(forgePath, forgeVersion->universal_url); ForgeInstaller forge(forgePath, forgeVersion->universal_url);
if (!forge.apply(m_version)) if (!forge.add(m_inst))
{ {
// failure notice QLOG_ERROR() << "Failure installing forge";
} }
} }
} }
m_inst->reloadFullVersion(this);
} }
void DerpModEditDialog::on_liteloaderBtn_clicked() void DerpModEditDialog::on_liteloaderBtn_clicked()
@ -180,6 +182,10 @@ void DerpModEditDialog::on_liteloaderBtn_clicked()
this, tr("LiteLoader"), this, tr("LiteLoader"),
tr("For reasons unknown, the LiteLoader installation failed. Check your MultiMC log files for details.")); tr("For reasons unknown, the LiteLoader installation failed. Check your MultiMC log files for details."));
} }
else
{
m_inst->reloadFullVersion(this);
}
} }
bool DerpModEditDialog::loaderListFilter(QKeyEvent *keyEvent) bool DerpModEditDialog::loaderListFilter(QKeyEvent *keyEvent)

66
logic/BaseInstaller.cpp Normal file
View File

@ -0,0 +1,66 @@
/* Copyright 2013 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 "BaseInstaller.h"
#include <QFile>
#include "DerpVersion.h"
#include "DerpLibrary.h"
#include "DerpInstance.h"
#include "cmdutils.h"
BaseInstaller::BaseInstaller()
{
}
bool BaseInstaller::isApplied(DerpInstance *on)
{
return QFile::exists(filename(on->instanceRoot()));
}
bool BaseInstaller::add(DerpInstance *to)
{
if (!patchesDir(to->instanceRoot()).exists())
{
QDir(to->instanceRoot()).mkdir("patches");
}
if (isApplied(to))
{
if (!remove(to))
{
return false;
}
}
return true;
}
bool BaseInstaller::remove(DerpInstance *from)
{
return QFile::remove(filename(from->instanceRoot()));
}
QString BaseInstaller::filename(const QString &root) const
{
return patchesDir(root).absoluteFilePath(id() + ".json");
}
QDir BaseInstaller::patchesDir(const QString &root) const
{
return QDir(root + "/patches/");
}

39
logic/BaseInstaller.h Normal file
View File

@ -0,0 +1,39 @@
/* Copyright 2013 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 <memory>
class DerpInstance;
class QDir;
class QString;
class BaseInstaller
{
public:
BaseInstaller();
virtual bool canApply(DerpInstance *instance) const { return true; }
bool isApplied(DerpInstance *on);
virtual bool add(DerpInstance *to);
virtual bool remove(DerpInstance *from);
protected:
virtual QString id() const = 0;
QString filename(const QString &root) const;
QDir patchesDir(const QString &root) const;
};

View File

@ -61,7 +61,7 @@ slots:
return; return;
} }
auto version = instance->getFullVersion(); auto version = instance->getFullVersion();
if (!forge.apply(version)) if (!forge.add(instance))
{ {
emitFailed(tr("Couldn't install Forge")); emitFailed(tr("Couldn't install Forge"));
return; return;

View File

@ -44,6 +44,26 @@ void DerpVersion::clear()
libraries.clear(); libraries.clear();
} }
void DerpVersion::dump() const
{
qDebug().nospace() << "DerpVersion("
<< "\n\tid=" << id
<< "\n\ttime=" << time
<< "\n\treleaseTime=" << releaseTime
<< "\n\ttype=" << type
<< "\n\tassets=" << assets
<< "\n\tprocessArguments=" << processArguments
<< "\n\tminecraftArguments=" << minecraftArguments
<< "\n\tminimumLauncherVersion=" << minimumLauncherVersion
<< "\n\tmainClass=" << mainClass
<< "\n\tlibraries=";
for (auto lib : libraries)
{
qDebug().nospace() << "\n\t\t" << lib.get();
}
qDebug().nospace() << "\n)";
}
QList<std::shared_ptr<DerpLibrary> > DerpVersion::getActiveNormalLibs() QList<std::shared_ptr<DerpLibrary> > DerpVersion::getActiveNormalLibs()
{ {
QList<std::shared_ptr<DerpLibrary> > output; QList<std::shared_ptr<DerpLibrary> > output;
@ -70,6 +90,16 @@ QList<std::shared_ptr<DerpLibrary> > DerpVersion::getActiveNativeLibs()
return output; return output;
} }
std::shared_ptr<DerpVersion> DerpVersion::fromJson(const QJsonObject &obj)
{
std::shared_ptr<DerpVersion> version(new DerpVersion(0));
if (DerpVersionBuilder::read(version.get(), obj))
{
return version;
}
return 0;
}
QVariant DerpVersion::data(const QModelIndex &index, int role) const QVariant DerpVersion::data(const QModelIndex &index, int role) const
{ {
if (!index.isValid()) if (!index.isValid())
@ -143,22 +173,7 @@ int DerpVersion::columnCount(const QModelIndex &parent) const
QDebug operator<<(QDebug &dbg, const DerpVersion *version) QDebug operator<<(QDebug &dbg, const DerpVersion *version)
{ {
dbg.nospace() << "DerpVersion(" version->dump();
<< "\n\tid=" << version->id
<< "\n\ttime=" << version->time
<< "\n\treleaseTime=" << version->releaseTime
<< "\n\ttype=" << version->type
<< "\n\tassets=" << version->assets
<< "\n\tprocessArguments=" << version->processArguments
<< "\n\tminecraftArguments=" << version->minecraftArguments
<< "\n\tminimumLauncherVersion=" << version->minimumLauncherVersion
<< "\n\tmainClass=" << version->mainClass
<< "\n\tlibraries=";
for (auto lib : version->libraries)
{
dbg.nospace() << "\n\t\t" << lib.get();
}
dbg.nospace() << "\n)";
return dbg.maybeSpace(); return dbg.maybeSpace();
} }
QDebug operator<<(QDebug &dbg, const DerpLibrary *library) QDebug operator<<(QDebug &dbg, const DerpLibrary *library)

View File

@ -41,10 +41,14 @@ public:
bool reload(QWidget *widgetParent); bool reload(QWidget *widgetParent);
void clear(); void clear();
void dump() const;
public: public:
QList<std::shared_ptr<DerpLibrary>> getActiveNormalLibs(); QList<std::shared_ptr<DerpLibrary>> getActiveNormalLibs();
QList<std::shared_ptr<DerpLibrary>> getActiveNativeLibs(); QList<std::shared_ptr<DerpLibrary>> getActiveNativeLibs();
static std::shared_ptr<DerpVersion> fromJson(const QJsonObject &obj);
// data members // data members
public: public:
/// the ID - determines which jar to use! ACTUALLY IMPORTANT! /// the ID - determines which jar to use! ACTUALLY IMPORTANT!

View File

@ -29,6 +29,7 @@
#include "DerpVersion.h" #include "DerpVersion.h"
#include "DerpInstance.h" #include "DerpInstance.h"
#include "DerpRule.h" #include "DerpRule.h"
#include "logger/QsLog.h"
DerpVersionBuilder::DerpVersionBuilder() DerpVersionBuilder::DerpVersionBuilder()
{ {
@ -44,6 +45,15 @@ bool DerpVersionBuilder::build(DerpVersion *version, DerpInstance *instance, QWi
return builder.build(); return builder.build();
} }
bool DerpVersionBuilder::read(DerpVersion *version, const QJsonObject &obj)
{
DerpVersionBuilder builder;
builder.m_version = version;
builder.m_instance = 0;
builder.m_widgetParent = 0;
return builder.read(obj);
}
bool DerpVersionBuilder::build() bool DerpVersionBuilder::build()
{ {
m_version->clear(); m_version->clear();
@ -55,6 +65,7 @@ bool DerpVersionBuilder::build()
// version.json // version.json
{ {
QLOG_INFO() << "Reading version.json";
QJsonObject obj; QJsonObject obj;
if (!read(QFileInfo(root.absoluteFilePath("version.json")), &obj)) if (!read(QFileInfo(root.absoluteFilePath("version.json")), &obj))
{ {
@ -73,6 +84,7 @@ bool DerpVersionBuilder::build()
QMap<int, QJsonObject> objects; QMap<int, QJsonObject> objects;
for (auto info : patches.entryInfoList(QStringList() << "*.json", QDir::Files)) for (auto info : patches.entryInfoList(QStringList() << "*.json", QDir::Files))
{ {
QLOG_INFO() << "Reading" << info.fileName();
QJsonObject obj; QJsonObject obj;
if (!read(info, &obj)) if (!read(info, &obj))
{ {
@ -87,6 +99,7 @@ bool DerpVersionBuilder::build()
} }
for (auto object : objects.values()) for (auto object : objects.values())
{ {
qDebug() << "Applying object with order" << objects.key(object);
if (!apply(object)) if (!apply(object))
{ {
return false; return false;
@ -98,6 +111,7 @@ bool DerpVersionBuilder::build()
{ {
if (QFile::exists(root.absoluteFilePath("custom.json"))) if (QFile::exists(root.absoluteFilePath("custom.json")))
{ {
QLOG_INFO() << "Reading custom.json";
QJsonObject obj; QJsonObject obj;
if (!read(QFileInfo(root.absoluteFilePath("custom.json")), &obj)) if (!read(QFileInfo(root.absoluteFilePath("custom.json")), &obj))
{ {
@ -113,6 +127,13 @@ bool DerpVersionBuilder::build()
return true; return true;
} }
bool DerpVersionBuilder::read(const QJsonObject &obj)
{
m_version->clear();
return apply(obj);
}
void applyString(const QJsonObject &obj, const QString &key, QString &out, const bool onlyOverride = true) void applyString(const QJsonObject &obj, const QString &key, QString &out, const bool onlyOverride = true)
{ {
if (obj.contains(key) && obj.value(key).isString()) if (obj.contains(key) && obj.value(key).isString())
@ -142,7 +163,9 @@ bool DerpVersionBuilder::apply(const QJsonObject &object)
{ {
applyString(object, "id", m_version->id); applyString(object, "id", m_version->id);
applyString(object, "mainClass", m_version->mainClass); applyString(object, "mainClass", m_version->mainClass);
applyString(object, "minecraftArguments", m_version->minecraftArguments, false);
applyString(object, "processArguments", m_version->processArguments, false); applyString(object, "processArguments", m_version->processArguments, false);
if (m_version->minecraftArguments.isEmpty())
{ {
const QString toCompare = m_version->processArguments.toLower(); const QString toCompare = m_version->processArguments.toLower();
if (toCompare == "legacy") if (toCompare == "legacy")
@ -158,7 +181,6 @@ bool DerpVersionBuilder::apply(const QJsonObject &object)
m_version->minecraftArguments = "--username ${auth_player_name} --session ${auth_session} --version ${profile_name}"; m_version->minecraftArguments = "--username ${auth_player_name} --session ${auth_session} --version ${profile_name}";
} }
} }
applyString(object, "minecraftArguments", m_version->minecraftArguments, false);
applyString(object, "type", m_version->type); applyString(object, "type", m_version->type);
applyString(object, "releaseTime", m_version->releaseTime); applyString(object, "releaseTime", m_version->releaseTime);
applyString(object, "time", m_version->time); applyString(object, "time", m_version->time);
@ -282,6 +304,18 @@ bool DerpVersionBuilder::applyLibrary(const QJsonObject &lib, const DerpVersionB
std::shared_ptr<DerpLibrary> library; std::shared_ptr<DerpLibrary> library;
if (lib.value("insert").toString() != "apply" && type == Add)
{
QMutableListIterator<std::shared_ptr<DerpLibrary> > it(m_version->libraries);
while (it.hasNext())
{
if (it.next()->rawName() == name)
{
it.remove();
}
}
}
if (lib.value("insert").toString() == "apply" && type == Add) if (lib.value("insert").toString() == "apply" && type == Add)
{ {
library = m_version->libraries[findLibrary(m_version->libraries, name)]; library = m_version->libraries[findLibrary(m_version->libraries, name)];
@ -343,7 +377,6 @@ bool DerpVersionBuilder::applyLibrary(const QJsonObject &lib, const DerpVersionB
library->finalize(); library->finalize();
if (type == Override) if (type == Override)
{ {
qDebug() << "appending" << library->rawName();
m_version->libraries.append(library); m_version->libraries.append(library);
} }
else if (lib.value("insert").toString() != "apply") else if (lib.value("insert").toString() != "apply")

View File

@ -28,6 +28,7 @@ class DerpVersionBuilder
DerpVersionBuilder(); DerpVersionBuilder();
public: public:
static bool build(DerpVersion *version, DerpInstance *instance, QWidget *widgetParent); static bool build(DerpVersion *version, DerpInstance *instance, QWidget *widgetParent);
static bool read(DerpVersion *version, const QJsonObject &obj);
private: private:
DerpVersion *m_version; DerpVersion *m_version;
@ -42,6 +43,7 @@ private:
}; };
bool build(); bool build();
bool read(const QJsonObject &obj);
void clear(); void clear();
bool apply(const QJsonObject &object); bool apply(const QJsonObject &object);

View File

@ -22,13 +22,13 @@
#include <pathutils.h> #include <pathutils.h>
#include <QStringList> #include <QStringList>
#include "MultiMC.h" #include "MultiMC.h"
#include "DerpInstance.h"
#include <QJsonDocument> #include <QJsonDocument>
#include <QJsonArray>
#include <QSaveFile> #include <QSaveFile>
#include <QCryptographicHash> #include <QCryptographicHash>
// DERPFIX
ForgeInstaller::ForgeInstaller(QString filename, QString universal_url) ForgeInstaller::ForgeInstaller(QString filename, QString universal_url)
{ {
std::shared_ptr<DerpVersion> newVersion; std::shared_ptr<DerpVersion> newVersion;
@ -64,7 +64,7 @@ ForgeInstaller::ForgeInstaller(QString filename, QString universal_url)
// read the forge version info // read the forge version info
{ {
// DERPFIX newVersion = DerpVersion::fromJson(versionInfoVal.toObject()); newVersion = DerpVersion::fromJson(versionInfoVal.toObject());
if (!newVersion) if (!newVersion)
return; return;
} }
@ -109,12 +109,22 @@ ForgeInstaller::ForgeInstaller(QString filename, QString universal_url)
realVersionId = m_forge_version->id = installObj.value("minecraft").toString(); realVersionId = m_forge_version->id = installObj.value("minecraft").toString();
} }
bool ForgeInstaller::apply(std::shared_ptr<DerpVersion> to) bool ForgeInstaller::add(DerpInstance *to)
{ {
if (!BaseInstaller::add(to))
{
return false;
}
QJsonObject obj;
obj.insert("order", 5);
if (!m_forge_version) if (!m_forge_version)
return false; return false;
int sliding_insert_window = 0; int sliding_insert_window = 0;
{ {
QJsonArray librariesPlus;
// for each library in the version we are adding (except for the blacklisted) // for each library in the version we are adding (except for the blacklisted)
QSet<QString> blacklist{"lwjgl", "lwjgl_util", "lwjgl-platform"}; QSet<QString> blacklist{"lwjgl", "lwjgl_util", "lwjgl-platform"};
for (auto lib : m_forge_version->libraries) for (auto lib : m_forge_version->libraries)
@ -133,27 +143,43 @@ bool ForgeInstaller::apply(std::shared_ptr<DerpVersion> to)
if (blacklist.contains(libName)) if (blacklist.contains(libName))
continue; continue;
// find an entry that matches this one QJsonObject libObj = lib->toJson();
bool found = false; bool found = false;
for (auto tolib : to->libraries) // find an entry that matches this one
for (auto tolib : to->getFullVersion()->libraries)
{ {
if (tolib->name() != libName) if (tolib->name() != libName)
continue; continue;
found = true; found = true;
// replace lib // replace lib
tolib = lib; libObj.insert("insert", QString("apply"));
break; break;
} }
if (!found) if (!found)
{ {
// add lib // add lib
to->libraries.insert(sliding_insert_window, lib); QJsonObject insertObj;
insertObj.insert("before", to->getFullVersion()->libraries.at(sliding_insert_window)->rawName());
libObj.insert("insert", insertObj);
sliding_insert_window++; sliding_insert_window++;
} }
librariesPlus.append(libObj);
} }
to->mainClass = m_forge_version->mainClass; obj.insert("+libraries", librariesPlus);
to->minecraftArguments = m_forge_version->minecraftArguments; obj.insert("mainClass", m_forge_version->mainClass);
to->processArguments = m_forge_version->processArguments; obj.insert("minecraftArguments", m_forge_version->minecraftArguments);
obj.insert("processArguments", m_forge_version->processArguments);
} }
QFile file(filename(to->instanceRoot()));
if (!file.open(QFile::WriteOnly))
{
QLOG_ERROR() << "Error opening" << file.fileName() << "for reading:" << file.errorString();
return false;
}
file.write(QJsonDocument(obj).toJson());
file.close();
return true; return true;
} }

View File

@ -14,17 +14,22 @@
*/ */
#pragma once #pragma once
#include "BaseInstaller.h"
#include <QString> #include <QString>
#include <memory> #include <memory>
class DerpVersion; class DerpVersion;
class ForgeInstaller class ForgeInstaller : public BaseInstaller
{ {
public: public:
ForgeInstaller(QString filename, QString universal_url); ForgeInstaller(QString filename, QString universal_url);
bool apply(std::shared_ptr<DerpVersion> to); bool add(DerpInstance *to) override;
QString id() const override { return "net.minecraftforge"; }
private: private:
// the version, read from the installer // the version, read from the installer

View File

@ -27,6 +27,7 @@
QMap<QString, QString> LiteLoaderInstaller::m_launcherWrapperVersionMapping; QMap<QString, QString> LiteLoaderInstaller::m_launcherWrapperVersionMapping;
LiteLoaderInstaller::LiteLoaderInstaller() LiteLoaderInstaller::LiteLoaderInstaller()
: BaseInstaller()
{ {
if (m_launcherWrapperVersionMapping.isEmpty()) if (m_launcherWrapperVersionMapping.isEmpty())
{ {
@ -42,24 +43,11 @@ bool LiteLoaderInstaller::canApply(DerpInstance *instance) const
return m_launcherWrapperVersionMapping.contains(instance->intendedVersionId()); return m_launcherWrapperVersionMapping.contains(instance->intendedVersionId());
} }
bool LiteLoaderInstaller::isApplied(DerpInstance *on)
{
return QFile::exists(filename(on->instanceRoot()));
}
bool LiteLoaderInstaller::add(DerpInstance *to) bool LiteLoaderInstaller::add(DerpInstance *to)
{ {
if (!patchesDir(to->instanceRoot()).exists()) if (!BaseInstaller::add(to))
{ {
QDir(to->instanceRoot()).mkdir("patches"); return false;
}
if (isApplied(to))
{
if (!remove(to))
{
return false;
}
} }
QJsonObject obj; QJsonObject obj;
@ -102,17 +90,3 @@ bool LiteLoaderInstaller::add(DerpInstance *to)
return true; return true;
} }
bool LiteLoaderInstaller::remove(DerpInstance *from)
{
return QFile::remove(filename(from->instanceRoot()));
}
QString LiteLoaderInstaller::filename(const QString &root) const
{
return patchesDir(root).absoluteFilePath(id() + ".json");
}
QDir LiteLoaderInstaller::patchesDir(const QString &root) const
{
return QDir(root + "/patches/");
}

View File

@ -14,30 +14,22 @@
*/ */
#pragma once #pragma once
#include "BaseInstaller.h"
#include <QString> #include <QString>
#include <QMap> #include <QMap>
#include <memory>
class DerpVersion; class LiteLoaderInstaller : public BaseInstaller
class DerpInstance;
class QDir;
// TODO base class
class LiteLoaderInstaller
{ {
public: public:
LiteLoaderInstaller(); LiteLoaderInstaller();
bool canApply(DerpInstance *instance) const; bool canApply(DerpInstance *instance) const override;
bool isApplied(DerpInstance *on); bool add(DerpInstance *to) override;
bool add(DerpInstance *to);
bool remove(DerpInstance *from);
private: private:
virtual QString id() const { return "com.mumfrey.liteloader"; } virtual QString id() const override { return "com.mumfrey.liteloader"; }
QString filename(const QString &root) const;
QDir patchesDir(const QString &root) const;
static QMap<QString, QString> m_launcherWrapperVersionMapping; static QMap<QString, QString> m_launcherWrapperVersionMapping;
}; };