NOISSUE Fix jar mods for OnesSix

This commit is contained in:
Petr Mrázek 2014-12-18 02:48:14 +01:00
parent 01f44e0f39
commit a30a9559c7
28 changed files with 445 additions and 1051 deletions

View File

@ -380,26 +380,19 @@ SET(MULTIMC_SOURCES
logic/InstanceFactory.cpp
logic/BaseInstance.h
logic/BaseInstance.cpp
logic/BaseInstance_p.h
logic/Mod.h
logic/Mod.cpp
logic/ModList.h
logic/ModList.cpp
# sets and maps for deciding based on versions
logic/VersionFilterData.h
logic/VersionFilterData.cpp
# Instance launch
logic/InstanceLauncher.h
logic/InstanceLauncher.cpp
logic/MinecraftProcess.h
logic/MinecraftProcess.cpp
# URN parser/resolver
logic/URNResolver.cpp
logic/URNResolver.h
# Annoying nag screen logic
logic/NagUtils.h
logic/NagUtils.cpp
@ -407,7 +400,7 @@ SET(MULTIMC_SOURCES
# Player skin utilities
logic/SkinUtils.h
logic/SkinUtils.cpp
# misc model filter
logic/EnabledItemFilter.h
logic/EnabledItemFilter.cpp
@ -476,7 +469,6 @@ SET(MULTIMC_SOURCES
# legacy instances
logic/LegacyInstance.h
logic/LegacyInstance.cpp
logic/LegacyInstance_p.h
logic/LegacyUpdate.h
logic/LegacyUpdate.cpp
@ -485,7 +477,10 @@ SET(MULTIMC_SOURCES
logic/OneSixUpdate.cpp
logic/OneSixInstance.h
logic/OneSixInstance.cpp
logic/OneSixInstance_p.h
# Common utils for instances
logic/JarUtils.h
logic/JarUtils.cpp
# OneSix version json infrastructure
logic/minecraft/GradleSpecifier.h
@ -597,7 +592,7 @@ SET(MULTIMC_SOURCES
logic/tools/JProfiler.cpp
logic/tools/JVisualVM.h
logic/tools/JVisualVM.cpp
# Forge and all things forge related
logic/forge/ForgeVersion.h
logic/forge/ForgeVersion.cpp
@ -612,7 +607,7 @@ SET(MULTIMC_SOURCES
logic/forge/LegacyForge.cpp
logic/forge/ForgeInstaller.h
logic/forge/ForgeInstaller.cpp
# Liteloader and related things
logic/liteloader/LiteLoaderInstaller.h
logic/liteloader/LiteLoaderInstaller.cpp

View File

@ -25,7 +25,6 @@
#include "logic/status/StatusChecker.h"
#include "logic/InstanceLauncher.h"
#include "logic/net/HttpMetaCache.h"
#include "logic/net/URLConstants.h"
@ -38,8 +37,6 @@
#include "logic/tools/JVisualVM.h"
#include "logic/tools/MCEditTool.h"
#include "logic/URNResolver.h"
#include "pathutils.h"
#include "cmdutils.h"
#include "logic/settings/INISettingsObject.h"
@ -83,13 +80,6 @@ MultiMC::MultiMC(int &argc, char **argv, bool test_mode) : QApplication(argc, ar
parser.addShortOpt("dir", 'd');
parser.addDocumentation("dir", "use the supplied directory as MultiMC root instead of "
"the binary location (use '.' for current)");
// WARNING: disabled until further notice
/*
// --launch
parser.addOption("launch");
parser.addShortOpt("launch", 'l');
parser.addDocumentation("launch", "tries to launch the given instance", "<inst>");
*/
// parse the arguments
try
@ -266,18 +256,6 @@ MultiMC::MultiMC(int &argc, char **argv, bool test_mode) : QApplication(argc, ar
tool->registerSettings(m_settings);
}
// launch instance, if that's what should be done
// WARNING: disabled until further notice
/*
if (!args["launch"].isNull())
{
if (InstanceLauncher(args["launch"].toString()).launch())
m_status = MultiMC::Succeeded;
else
m_status = MultiMC::Failed;
return;
}
*/
connect(this, SIGNAL(aboutToQuit()), SLOT(onExit()));
m_status = MultiMC::Initialized;
}
@ -704,15 +682,6 @@ std::shared_ptr<JavaVersionList> MultiMC::javalist()
return m_javalist;
}
std::shared_ptr<URNResolver> MultiMC::resolver()
{
if (!m_resolver)
{
m_resolver.reset(new URNResolver());
}
return m_resolver;
}
void MultiMC::installUpdates(const QString updateFilesDir, UpdateFlags flags)
{
// if we are going to update on exit, save the params now

View File

@ -23,7 +23,6 @@ class NewsChecker;
class StatusChecker;
class BaseProfilerFactory;
class BaseDetachedToolFactory;
class URNResolver;
class TranslationDownloader;
#if defined(MMC)
@ -118,8 +117,6 @@ public:
std::shared_ptr<JavaVersionList> javalist();
std::shared_ptr<URNResolver> resolver();
QMap<QString, std::shared_ptr<BaseProfilerFactory>> profilers()
{
return m_profilers;
@ -206,7 +203,6 @@ private:
std::shared_ptr<LiteLoaderVersionList> m_liteloaderlist;
std::shared_ptr<MinecraftVersionList> m_minecraftlist;
std::shared_ptr<JavaVersionList> m_javalist;
std::shared_ptr<URNResolver> m_resolver;
std::shared_ptr<TranslationDownloader> m_translationChecker;
QMap<QString, std::shared_ptr<BaseProfilerFactory>> m_profilers;

View File

@ -1,77 +0,0 @@
/* Copyright 2013-2014 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// CAUTION:
// This file contains all manner of hackery and insanity.
// I will not be responsible for any loss of sanity due to reading this code.
// Here be dragons!
#include "WinBacktrace.h"
#include <windows.h>
#ifndef __i386__
#error WinBacktrace is only supported on x86 architectures.
#endif
// We need to do some crazy shit to walk through the stack.
// Windows unwinds the stack when an exception is thrown, so we
// need to examine the EXCEPTION_POINTERS's CONTEXT.
size_t getBacktrace(StackFrame *stack, size_t size, CONTEXT ctx)
{
// Written using information and a bit of pseudocode from
// http://www.eptacom.net/pubblicazioni/pub_eng/except.html
// This is probably one of the most horrifying things I've ever written.
// This tracks whether the current EBP is valid.
// When an invalid EBP is encountered, we stop walking the stack.
bool validEBP = true;
DWORD ebp = ctx.Ebp; // The current EBP (Extended Base Pointer)
DWORD eip = ctx.Eip;
int i;
for (i = 0; i < size; i++)
{
if (ebp & 3)
validEBP = false;
// FIXME: This function is obsolete, according to MSDN.
else if (IsBadReadPtr((void*) ebp, 8))
validEBP = false;
if (!validEBP) break;
// Find the caller.
// On the first iteration, the caller is whatever EIP points to.
// On successive iterations, the caller is the byte after EBP.
BYTE* caller = !i ? (BYTE*)eip : *((BYTE**) ebp + 1);
// The first ebp is the EBP from the CONTEXT.
// On successive iterations, the EBP is the DWORD that the previous EBP points to.
ebp = !i ? ebp : *(DWORD*)ebp;
// Find the caller's module.
// We'll use VirtualQuery to get information about the caller's address.
MEMORY_BASIC_INFORMATION mbi;
VirtualQuery(caller, &mbi, sizeof(mbi));
// We can get the instance handle from the allocation base.
HINSTANCE hInst = (HINSTANCE)mbi.AllocationBase;
// If the handle is 0, then the EBP is invalid.
if (hInst == 0) validEBP = false;
// Otherwise, dump info about the caller.
else stack[i].address = (void*)caller;
}
return i;
}

View File

@ -1,44 +0,0 @@
/* Copyright 2013-2014 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <windows.h>
#ifndef SF_STR_LEN
// The max length of all strings in the StackFrame struct.
// Because it must be stack allocated, this must be known at compile time.
// Stuff longer than this will be truncated.
// Defaults to 4096 (4kB)
#define SF_STR_LEN 4096
#endif
// Data structure for holding information about a stack frame.
// There's some more hackery in here so it can be allocated on the stack.
struct StackFrame
{
// The address of this stack frame.
void* address;
// The name of the function at this address.
char funcName[SF_STR_LEN];
};
// This function walks through the given CONTEXT structure, extracting a
// backtrace from it.
// The backtrace will be put into the array given by the `stack` argument
// with a maximum length of `size`.
// This function returns the size of the backtrace retrieved.
size_t getBacktrace(StackFrame* stack, size_t size, CONTEXT ctx);

View File

@ -15,7 +15,6 @@
#include "MultiMC.h"
#include "BaseInstance.h"
#include "BaseInstance_p.h"
#include <QFileInfo>
#include <QDir>
@ -31,61 +30,50 @@
#include "logic/icons/IconList.h"
#include "logic/InstanceList.h"
BaseInstance::BaseInstance(BaseInstancePrivate *d_in, const QString &rootDir,
SettingsObject *settings_obj, QObject *parent)
: QObject(parent), inst_d(d_in)
BaseInstance::BaseInstance(const QString &rootDir, SettingsObject *settings, QObject *parent)
: QObject(parent)
{
I_D(BaseInstance);
d->m_settings = std::shared_ptr<SettingsObject>(settings_obj);
d->m_rootDir = rootDir;
settings().registerSetting("name", "Unnamed Instance");
settings().registerSetting("iconKey", "default");
m_settings = std::shared_ptr<SettingsObject>(settings);
m_rootDir = rootDir;
m_settings->registerSetting("name", "Unnamed Instance");
m_settings->registerSetting("iconKey", "default");
connect(MMC->icons().get(), SIGNAL(iconUpdated(QString)), SLOT(iconUpdated(QString)));
settings().registerSetting("notes", "");
settings().registerSetting("lastLaunchTime", 0);
/*
* custom base jar has no default. it is determined in code... see the accessor methods for
*it
*
* for instances that DO NOT have the CustomBaseJar setting (legacy instances),
* [.]minecraft/bin/mcbackup.jar is the default base jar
*/
settings().registerSetting("UseCustomBaseJar", true);
settings().registerSetting("CustomBaseJar", "");
m_settings->registerSetting("notes", "");
m_settings->registerSetting("lastLaunchTime", 0);
auto globalSettings = MMC->settings();
// Java Settings
settings().registerSetting("OverrideJava", false);
settings().registerSetting("OverrideJavaLocation", false);
settings().registerSetting("OverrideJavaArgs", false);
settings().registerOverride(globalSettings->getSetting("JavaPath"));
settings().registerOverride(globalSettings->getSetting("JvmArgs"));
m_settings->registerSetting("OverrideJava", false);
m_settings->registerSetting("OverrideJavaLocation", false);
m_settings->registerSetting("OverrideJavaArgs", false);
m_settings->registerOverride(globalSettings->getSetting("JavaPath"));
m_settings->registerOverride(globalSettings->getSetting("JvmArgs"));
// Custom Commands
settings().registerSetting({"OverrideCommands","OverrideLaunchCmd"}, false);
settings().registerOverride(globalSettings->getSetting("PreLaunchCommand"));
settings().registerOverride(globalSettings->getSetting("PostExitCommand"));
m_settings->registerSetting({"OverrideCommands","OverrideLaunchCmd"}, false);
m_settings->registerOverride(globalSettings->getSetting("PreLaunchCommand"));
m_settings->registerOverride(globalSettings->getSetting("PostExitCommand"));
// Window Size
settings().registerSetting("OverrideWindow", false);
settings().registerOverride(globalSettings->getSetting("LaunchMaximized"));
settings().registerOverride(globalSettings->getSetting("MinecraftWinWidth"));
settings().registerOverride(globalSettings->getSetting("MinecraftWinHeight"));
m_settings->registerSetting("OverrideWindow", false);
m_settings->registerOverride(globalSettings->getSetting("LaunchMaximized"));
m_settings->registerOverride(globalSettings->getSetting("MinecraftWinWidth"));
m_settings->registerOverride(globalSettings->getSetting("MinecraftWinHeight"));
// Memory
settings().registerSetting("OverrideMemory", false);
settings().registerOverride(globalSettings->getSetting("MinMemAlloc"));
settings().registerOverride(globalSettings->getSetting("MaxMemAlloc"));
settings().registerOverride(globalSettings->getSetting("PermGen"));
m_settings->registerSetting("OverrideMemory", false);
m_settings->registerOverride(globalSettings->getSetting("MinMemAlloc"));
m_settings->registerOverride(globalSettings->getSetting("MaxMemAlloc"));
m_settings->registerOverride(globalSettings->getSetting("PermGen"));
// Console
settings().registerSetting("OverrideConsole", false);
settings().registerOverride(globalSettings->getSetting("ShowConsole"));
settings().registerOverride(globalSettings->getSetting("AutoCloseConsole"));
settings().registerOverride(globalSettings->getSetting("LogPrePostOutput"));
m_settings->registerSetting("OverrideConsole", false);
m_settings->registerOverride(globalSettings->getSetting("ShowConsole"));
m_settings->registerOverride(globalSettings->getSetting("AutoCloseConsole"));
m_settings->registerOverride(globalSettings->getSetting("LogPrePostOutput"));
}
void BaseInstance::iconUpdated(QString key)
@ -109,26 +97,22 @@ QString BaseInstance::id() const
bool BaseInstance::isRunning() const
{
I_D(BaseInstance);
return d->m_isRunning;
return m_isRunning;
}
void BaseInstance::setRunning(bool running) const
void BaseInstance::setRunning(bool running)
{
I_D(BaseInstance);
d->m_isRunning = running;
m_isRunning = running;
}
QString BaseInstance::instanceType() const
{
I_D(BaseInstance);
return d->m_settings->get("InstanceType").toString();
return m_settings->get("InstanceType").toString();
}
QString BaseInstance::instanceRoot() const
{
I_D(BaseInstance);
return d->m_rootDir;
return m_rootDir;
}
QString BaseInstance::minecraftRoot() const
@ -159,36 +143,34 @@ std::shared_ptr<BaseVersionList> BaseInstance::versionList() const
SettingsObject &BaseInstance::settings() const
{
I_D(BaseInstance);
return *d->m_settings;
return *m_settings;
}
BaseInstance::InstanceFlags BaseInstance::flags() const
{
I_D(const BaseInstance);
return d->m_flags;
return m_flags;
}
void BaseInstance::setFlags(const InstanceFlags &flags)
{
I_D(BaseInstance);
if (flags != d->m_flags)
if (flags != m_flags)
{
d->m_flags = flags;
m_flags = flags;
emit flagsChanged();
emit propertiesChanged(this);
}
}
void BaseInstance::setFlag(const BaseInstance::InstanceFlag flag)
{
I_D(BaseInstance);
d->m_flags |= flag;
m_flags |= flag;
emit flagsChanged();
emit propertiesChanged(this);
}
void BaseInstance::unsetFlag(const BaseInstance::InstanceFlag flag)
{
I_D(BaseInstance);
d->m_flags &= ~flag;
m_flags &= ~flag;
emit flagsChanged();
emit propertiesChanged(this);
}
@ -200,69 +182,23 @@ bool BaseInstance::canLaunch() const
bool BaseInstance::reload()
{
return settings().reload();
}
QString BaseInstance::baseJar() const
{
I_D(BaseInstance);
bool customJar = d->m_settings->get("UseCustomBaseJar").toBool();
if (customJar)
{
return customBaseJar();
}
else
return defaultBaseJar();
}
QString BaseInstance::customBaseJar() const
{
I_D(BaseInstance);
QString value = d->m_settings->get("CustomBaseJar").toString();
if (value.isNull() || value.isEmpty())
{
return defaultCustomBaseJar();
}
return value;
}
void BaseInstance::setCustomBaseJar(QString val)
{
I_D(BaseInstance);
if (val.isNull() || val.isEmpty() || val == defaultCustomBaseJar())
d->m_settings->reset("CustomBaseJar");
else
d->m_settings->set("CustomBaseJar", val);
}
void BaseInstance::setShouldUseCustomBaseJar(bool val)
{
I_D(BaseInstance);
d->m_settings->set("UseCustomBaseJar", val);
}
bool BaseInstance::shouldUseCustomBaseJar() const
{
I_D(BaseInstance);
return d->m_settings->get("UseCustomBaseJar").toBool();
return m_settings->reload();
}
qint64 BaseInstance::lastLaunch() const
{
I_D(BaseInstance);
return d->m_settings->get("lastLaunchTime").value<qint64>();
return m_settings->get("lastLaunchTime").value<qint64>();
}
void BaseInstance::setLastLaunch(qint64 val)
{
I_D(BaseInstance);
d->m_settings->set("lastLaunchTime", val);
m_settings->set("lastLaunchTime", val);
emit propertiesChanged(this);
}
void BaseInstance::setGroupInitial(QString val)
{
I_D(BaseInstance);
d->m_group = val;
m_group = val;
emit propertiesChanged(this);
}
@ -274,44 +210,39 @@ void BaseInstance::setGroupPost(QString val)
QString BaseInstance::group() const
{
I_D(BaseInstance);
return d->m_group;
return m_group;
}
void BaseInstance::setNotes(QString val)
{
I_D(BaseInstance);
d->m_settings->set("notes", val);
m_settings->set("notes", val);
}
QString BaseInstance::notes() const
{
I_D(BaseInstance);
return d->m_settings->get("notes").toString();
return m_settings->get("notes").toString();
}
void BaseInstance::setIconKey(QString val)
{
I_D(BaseInstance);
d->m_settings->set("iconKey", val);
m_settings->set("iconKey", val);
emit propertiesChanged(this);
}
QString BaseInstance::iconKey() const
{
I_D(BaseInstance);
return d->m_settings->get("iconKey").toString();
return m_settings->get("iconKey").toString();
}
void BaseInstance::setName(QString val)
{
I_D(BaseInstance);
d->m_settings->set("name", val);
m_settings->set("name", val);
emit propertiesChanged(this);
}
QString BaseInstance::name() const
{
I_D(BaseInstance);
return d->m_settings->get("name").toString();
return m_settings->get("name").toString();
}
QString BaseInstance::windowTitle() const

View File

@ -51,8 +51,7 @@ class BaseInstance : public QObject
Q_OBJECT
protected:
/// no-touchy!
BaseInstance(BaseInstancePrivate *d, const QString &rootDir, SettingsObject *settings,
QObject *parent = 0);
BaseInstance(const QString &rootDir, SettingsObject *settings, QObject *parent = 0);
public:
/// virtual destructor to make sure the destruction is COMPLETE
@ -69,8 +68,8 @@ public:
/// be unique.
virtual QString id() const;
virtual void setRunning(bool running) const;
virtual bool isRunning() const;
void setRunning(bool running);
bool isRunning() const;
/// get the type of this instance
QString instanceType() const;
@ -127,30 +126,10 @@ public:
{
return nullptr;
}
/// Traits. Normally inside the version, depends on instance implementation.
virtual QSet <QString> traits() = 0;
/// Get the curent base jar of this instance. By default, it's the
/// versions/$version/$version.jar
QString baseJar() const;
/// the default base jar of this instance
virtual QString defaultBaseJar() const = 0;
/// the default custom base jar of this instance
virtual QString defaultCustomBaseJar() const = 0;
/*!
* Whether or not custom base jar is used
*/
bool shouldUseCustomBaseJar() const;
void setShouldUseCustomBaseJar(bool val);
/*!
* The value of the custom base jar
*/
QString customBaseJar() const;
void setCustomBaseJar(QString val);
/**
* Gets the time that the instance was last launched.
* Stored in milliseconds since epoch.
@ -202,7 +181,7 @@ public:
VersionBrokenFlag = 0x01,
UpdateAvailable = 0x02
};
Q_DECLARE_FLAGS(InstanceFlags, InstanceFlag)
Q_DECLARE_FLAGS(InstanceFlags, InstanceFlag);
InstanceFlags flags() const;
void setFlags(const InstanceFlags &flags);
void setFlag(const InstanceFlag flag);
@ -232,7 +211,11 @@ protected slots:
void iconUpdated(QString key);
protected:
std::shared_ptr<BaseInstancePrivate> inst_d;
QString m_rootDir;
QString m_group;
std::shared_ptr<SettingsObject> m_settings;
InstanceFlags m_flags;
bool m_isRunning = false;
};
Q_DECLARE_METATYPE(std::shared_ptr<BaseInstance>)

View File

@ -1,36 +0,0 @@
/* Copyright 2013-2014 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <QString>
#include <QSet>
#include "logic/settings/SettingsObject.h"
#include "BaseInstance.h"
#define I_D(Class) Class##Private *const d = (Class##Private * const)inst_d.get()
class BaseInstancePrivate
{
public:
virtual ~BaseInstancePrivate(){};
QString m_rootDir;
QString m_group;
std::shared_ptr<SettingsObject> m_settings;
BaseInstance::InstanceFlags m_flags;
bool m_isRunning = false;
};

View File

@ -100,7 +100,6 @@ InstanceFactory::InstCreateError InstanceFactory::createInstance(InstancePtr &in
m_settings->set("InstanceType", "OneSix");
inst.reset(new OneSixInstance(instDir, m_settings));
inst->setIntendedVersionId(version->descriptor());
inst->setShouldUseCustomBaseJar(false);
}
else if (type == FTBInstance)
{
@ -109,14 +108,12 @@ InstanceFactory::InstCreateError InstanceFactory::createInstance(InstancePtr &in
m_settings->set("InstanceType", "LegacyFTB");
inst.reset(new LegacyFTBInstance(instDir, m_settings));
inst->setIntendedVersionId(version->descriptor());
inst->setShouldUseCustomBaseJar(false);
}
else
{
m_settings->set("InstanceType", "OneSixFTB");
inst.reset(new OneSixFTBInstance(instDir, m_settings));
inst->setIntendedVersionId(version->descriptor());
inst->setShouldUseCustomBaseJar(false);
}
}
else

View File

@ -1,94 +0,0 @@
/* Copyright 2013-2014 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <iostream>
#include "InstanceLauncher.h"
#include "MultiMC.h"
#include "gui/ConsoleWindow.h"
#include "gui/dialogs/ProgressDialog.h"
#include "logic/MinecraftProcess.h"
#include "logic/InstanceList.h"
InstanceLauncher::InstanceLauncher(QString instId) : QObject(), instId(instId)
{
}
void InstanceLauncher::onTerminated()
{
std::cout << "Minecraft exited" << std::endl;
MMC->quit();
}
void InstanceLauncher::onLoginComplete()
{
// TODO: Fix this.
/*
LoginTask *task = (LoginTask *)QObject::sender();
auto result = task->getResult();
auto instance = MMC->instances()->getInstanceById(instId);
proc = instance->prepareForLaunch(result);
if (!proc)
{
// FIXME: report error
return;
}
console = new ConsoleWindow(proc);
connect(console, SIGNAL(isClosing()), this, SLOT(onTerminated()));
proc->setLogin(result.username, result.session_id);
proc->launch();
*/
}
void InstanceLauncher::doLogin(const QString &errorMsg)
{
// FIXME: Use new account system here...
/*
LoginDialog *loginDlg = new LoginDialog(nullptr, errorMsg);
loginDlg->exec();
if (loginDlg->result() == QDialog::Accepted)
{
PasswordLogin uInfo{loginDlg->getUsername(), loginDlg->getPassword()};
ProgressDialog *tDialog = new ProgressDialog(nullptr);
LoginTask *loginTask = new LoginTask(uInfo, tDialog);
connect(loginTask, SIGNAL(succeeded()), SLOT(onLoginComplete()), Qt::QueuedConnection);
connect(loginTask, SIGNAL(failed(QString)), SLOT(doLogin(QString)),
Qt::QueuedConnection);
tDialog->exec(loginTask);
}
*/
// onLoginComplete(LoginResponse("Offline","Offline", 1));
}
int InstanceLauncher::launch()
{
std::cout << "Launching Instance '" << qPrintable(instId) << "'" << std::endl;
auto instance = MMC->instances()->getInstanceById(instId);
if (!instance)
{
std::cout << "Could not find instance requested. note that you have to specify the ID, "
"not the NAME" << std::endl;
return 1;
}
std::cout << "Logging in..." << std::endl;
doLogin("");
return MMC->exec();
}

View File

@ -1,44 +0,0 @@
/* Copyright 2013-2014 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <QObject>
class MinecraftProcess;
class ConsoleWindow;
// Commandline instance launcher
class InstanceLauncher : public QObject
{
Q_OBJECT
private:
QString instId;
MinecraftProcess *proc;
ConsoleWindow *console;
public:
InstanceLauncher(QString instId);
private
slots:
void onTerminated();
void onLoginComplete();
void doLogin(const QString &errorMsg);
public:
int launch();
};

161
logic/JarUtils.cpp Normal file
View File

@ -0,0 +1,161 @@
#include "JarUtils.h"
#include <quazip.h>
#include <quazipfile.h>
#include <JlCompress.h>
#include <logger/QsLog.h>
namespace JarUtils {
bool mergeZipFiles(QuaZip *into, QFileInfo from, QSet<QString> &contained,
std::function<bool(QString)> filter)
{
QuaZip modZip(from.filePath());
modZip.open(QuaZip::mdUnzip);
QuaZipFile fileInsideMod(&modZip);
QuaZipFile zipOutFile(into);
for (bool more = modZip.goToFirstFile(); more; more = modZip.goToNextFile())
{
QString filename = modZip.getCurrentFileName();
if (!filter(filename))
{
QLOG_INFO() << "Skipping file " << filename << " from "
<< from.fileName() << " - filtered";
continue;
}
if (contained.contains(filename))
{
QLOG_INFO() << "Skipping already contained file " << filename << " from "
<< from.fileName();
continue;
}
contained.insert(filename);
QLOG_INFO() << "Adding file " << filename << " from " << from.fileName();
if (!fileInsideMod.open(QIODevice::ReadOnly))
{
QLOG_ERROR() << "Failed to open " << filename << " from " << from.fileName();
return false;
}
QuaZipNewInfo info_out(fileInsideMod.getActualFileName());
if (!zipOutFile.open(QIODevice::WriteOnly, info_out))
{
QLOG_ERROR() << "Failed to open " << filename << " in the jar";
fileInsideMod.close();
return false;
}
if (!JlCompress::copyData(fileInsideMod, zipOutFile))
{
zipOutFile.close();
fileInsideMod.close();
QLOG_ERROR() << "Failed to copy data of " << filename << " into the jar";
return false;
}
zipOutFile.close();
fileInsideMod.close();
}
return true;
}
bool createModdedJar(QString sourceJarPath, QString targetJarPath, const QList<Mod>& mods)
{
QuaZip zipOut(targetJarPath);
if (!zipOut.open(QuaZip::mdCreate))
{
QFile::remove(targetJarPath);
QLOG_ERROR() << "Failed to open the minecraft.jar for modding";
return false;
}
// Files already added to the jar.
// These files will be skipped.
QSet<QString> addedFiles;
// Modify the jar
QListIterator<Mod> i(mods);
i.toBack();
while (i.hasPrevious())
{
const Mod &mod = i.previous();
// do not merge disabled mods.
if (!mod.enabled())
continue;
if (mod.type() == Mod::MOD_ZIPFILE)
{
if (!mergeZipFiles(&zipOut, mod.filename(), addedFiles, noFilter))
{
zipOut.close();
QFile::remove(targetJarPath);
QLOG_ERROR() << "Failed to add" << mod.filename().fileName() << "to the jar.";
return false;
}
}
else if (mod.type() == Mod::MOD_SINGLEFILE)
{
auto filename = mod.filename();
if (!JlCompress::compressFile(&zipOut, filename.absoluteFilePath(),
filename.fileName()))
{
zipOut.close();
QFile::remove(targetJarPath);
QLOG_ERROR() << "Failed to add" << mod.filename().fileName() << "to the jar.";
return false;
}
addedFiles.insert(filename.fileName());
QLOG_INFO() << "Adding file " << filename.fileName() << " from "
<< filename.absoluteFilePath();
}
else if (mod.type() == Mod::MOD_FOLDER)
{
auto filename = mod.filename();
QString what_to_zip = filename.absoluteFilePath();
QDir dir(what_to_zip);
dir.cdUp();
QString parent_dir = dir.absolutePath();
if (!JlCompress::compressSubDir(&zipOut, what_to_zip, parent_dir, true, addedFiles))
{
zipOut.close();
QFile::remove(targetJarPath);
QLOG_ERROR() << "Failed to add" << mod.filename().fileName() << "to the jar.";
return false;
}
QLOG_INFO() << "Adding folder " << filename.fileName() << " from "
<< filename.absoluteFilePath();
}
}
if (!mergeZipFiles(&zipOut, QFileInfo(sourceJarPath), addedFiles, metaInfFilter))
{
zipOut.close();
QFile::remove(targetJarPath);
QLOG_ERROR() << "Failed to insert minecraft.jar contents.";
return false;
}
// Recompress the jar
zipOut.close();
if (zipOut.getZipError() != 0)
{
QFile::remove(targetJarPath);
QLOG_ERROR() << "Failed to finalize minecraft.jar!";
return false;
}
return true;
}
bool noFilter(QString)
{
return true;
}
bool metaInfFilter(QString key)
{
if(key.contains("META-INF"))
{
return false;
}
return true;
}
}

18
logic/JarUtils.h Normal file
View File

@ -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);
}

View File

@ -23,7 +23,6 @@
#include "MultiMC.h"
#include "LegacyInstance.h"
#include "LegacyInstance_p.h"
#include "logic/MinecraftProcess.h"
#include "logic/LegacyUpdate.h"
@ -36,15 +35,23 @@
#include <gui/pages/NotesPage.h>
#include <gui/pages/ScreenshotsPage.h>
LegacyInstance::LegacyInstance(const QString &rootDir, SettingsObject *settings,
QObject *parent)
: BaseInstance(new LegacyInstancePrivate(), rootDir, settings, parent)
LegacyInstance::LegacyInstance(const QString &rootDir, SettingsObject *settings, QObject *parent)
: BaseInstance(rootDir, settings, parent)
{
settings->registerSetting("NeedsRebuild", true);
settings->registerSetting("ShouldUpdate", false);
settings->registerSetting("JarVersion", "Unknown");
settings->registerSetting("LwjglVersion", "2.9.0");
settings->registerSetting("IntendedJarVersion", "");
/*
* custom base jar has no default. it is determined in code... see the accessor methods for
*it
*
* for instances that DO NOT have the CustomBaseJar setting (legacy instances),
* [.]minecraft/bin/mcbackup.jar is the default base jar
*/
settings->registerSetting("UseCustomBaseJar", true);
settings->registerSetting("CustomBaseJar", "");
}
QList<BasePage *> LegacyInstance::getPages()
@ -69,6 +76,46 @@ QString LegacyInstance::dialogTitle()
return tr("Edit Instance (%1)").arg(name());
}
QString LegacyInstance::baseJar() const
{
bool customJar = m_settings->get("UseCustomBaseJar").toBool();
if (customJar)
{
return customBaseJar();
}
else
return defaultBaseJar();
}
QString LegacyInstance::customBaseJar() const
{
QString value = m_settings->get("CustomBaseJar").toString();
if (value.isNull() || value.isEmpty())
{
return defaultCustomBaseJar();
}
return value;
}
void LegacyInstance::setCustomBaseJar(QString val)
{
if (val.isNull() || val.isEmpty() || val == defaultCustomBaseJar())
m_settings->reset("CustomBaseJar");
else
m_settings->set("CustomBaseJar", val);
}
void LegacyInstance::setShouldUseCustomBaseJar(bool val)
{
m_settings->set("UseCustomBaseJar", val);
}
bool LegacyInstance::shouldUseCustomBaseJar() const
{
return m_settings->get("UseCustomBaseJar").toBool();
}
std::shared_ptr<Task> LegacyInstance::doUpdate()
{
// make sure the jar mods list is initialized by asking for it.
@ -113,26 +160,24 @@ void LegacyInstance::cleanupAfterRun()
std::shared_ptr<ModList> LegacyInstance::coreModList()
{
I_D(LegacyInstance);
if (!d->core_mod_list)
if (!core_mod_list)
{
d->core_mod_list.reset(new ModList(coreModsDir()));
core_mod_list.reset(new ModList(coreModsDir()));
}
d->core_mod_list->update();
return d->core_mod_list;
core_mod_list->update();
return core_mod_list;
}
std::shared_ptr<ModList> LegacyInstance::jarModList()
{
I_D(LegacyInstance);
if (!d->jar_mod_list)
if (!jar_mod_list)
{
auto list = new ModList(jarModsDir(), modListFile());
connect(list, SIGNAL(changed()), SLOT(jarModsChanged()));
d->jar_mod_list.reset(list);
jar_mod_list.reset(list);
}
d->jar_mod_list->update();
return d->jar_mod_list;
jar_mod_list->update();
return jar_mod_list;
}
void LegacyInstance::jarModsChanged()
@ -143,24 +188,22 @@ void LegacyInstance::jarModsChanged()
std::shared_ptr<ModList> LegacyInstance::loaderModList()
{
I_D(LegacyInstance);
if (!d->loader_mod_list)
if (!loader_mod_list)
{
d->loader_mod_list.reset(new ModList(loaderModsDir()));
loader_mod_list.reset(new ModList(loaderModsDir()));
}
d->loader_mod_list->update();
return d->loader_mod_list;
loader_mod_list->update();
return loader_mod_list;
}
std::shared_ptr<ModList> LegacyInstance::texturePackList()
{
I_D(LegacyInstance);
if (!d->texture_pack_list)
if (!texture_pack_list)
{
d->texture_pack_list.reset(new ModList(texturePacksDir()));
texture_pack_list.reset(new ModList(texturePacksDir()));
}
d->texture_pack_list->update();
return d->texture_pack_list;
texture_pack_list->update();
return texture_pack_list;
}
QString LegacyInstance::jarModsDir() const
@ -219,38 +262,32 @@ QString LegacyInstance::instanceConfigFolder() const
bool LegacyInstance::shouldRebuild() const
{
I_D(LegacyInstance);
return d->m_settings->get("NeedsRebuild").toBool();
return m_settings->get("NeedsRebuild").toBool();
}
void LegacyInstance::setShouldRebuild(bool val)
{
I_D(LegacyInstance);
d->m_settings->set("NeedsRebuild", val);
m_settings->set("NeedsRebuild", val);
}
QString LegacyInstance::currentVersionId() const
{
I_D(LegacyInstance);
return d->m_settings->get("JarVersion").toString();
return m_settings->get("JarVersion").toString();
}
QString LegacyInstance::lwjglVersion() const
{
I_D(LegacyInstance);
return d->m_settings->get("LwjglVersion").toString();
return m_settings->get("LwjglVersion").toString();
}
void LegacyInstance::setLWJGLVersion(QString val)
{
I_D(LegacyInstance);
d->m_settings->set("LwjglVersion", val);
m_settings->set("LwjglVersion", val);
}
QString LegacyInstance::intendedVersionId() const
{
I_D(LegacyInstance);
return d->m_settings->get("IntendedJarVersion").toString();
return m_settings->get("IntendedJarVersion").toString();
}
bool LegacyInstance::setIntendedVersionId(QString version)

View File

@ -56,6 +56,27 @@ public:
QString resourceDir() const;
virtual QString instanceConfigFolder() const override;
/// Get the curent base jar of this instance. By default, it's the
/// versions/$version/$version.jar
QString baseJar() const;
/// the default base jar of this instance
QString defaultBaseJar() const;
/// the default custom base jar of this instance
QString defaultCustomBaseJar() const;
/*!
* Whether or not custom base jar is used
*/
bool shouldUseCustomBaseJar() const;
void setShouldUseCustomBaseJar(bool val);
/*!
* The value of the custom base jar
*/
QString customBaseJar() const;
void setCustomBaseJar(QString val);
/*!
* Whether or not the instance's minecraft.jar needs to be rebuilt.
* If this is true, when the instance launches, its jar mods will be
@ -92,11 +113,14 @@ public:
virtual bool prepareForLaunch(AuthSessionPtr account, QString & launchScript) override;
virtual void cleanupAfterRun() override;
virtual QString defaultBaseJar() const override;
virtual QString defaultCustomBaseJar() const override;
virtual QString getStatusbarDescription() override;
protected:
std::shared_ptr<ModList> jar_mod_list;
std::shared_ptr<ModList> core_mod_list;
std::shared_ptr<ModList> loader_mod_list;
std::shared_ptr<ModList> texture_pack_list;
protected
slots:
virtual void jarModsChanged();

View File

@ -1,32 +0,0 @@
/* Copyright 2013-2014 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <QString>
#include "logic/settings/SettingsObject.h"
#include <memory>
#include "BaseInstance_p.h"
#include "ModList.h"
class LegacyInstancePrivate : public BaseInstancePrivate
{
public:
virtual ~LegacyInstancePrivate() {};
std::shared_ptr<ModList> jar_mod_list;
std::shared_ptr<ModList> core_mod_list;
std::shared_ptr<ModList> loader_mod_list;
std::shared_ptr<ModList> texture_pack_list;
};

View File

@ -30,6 +30,7 @@
#include "logger/QsLog.h"
#include "logic/net/URLConstants.h"
#include "JarUtils.h"
LegacyUpdate::LegacyUpdate(BaseInstance *inst, QObject *parent) : Task(parent), m_inst(inst)
@ -38,25 +39,7 @@ LegacyUpdate::LegacyUpdate(BaseInstance *inst, QObject *parent) : Task(parent),
void LegacyUpdate::executeTask()
{
/*
if(m_only_prepare)
{
// FIXME: think this through some more.
LegacyInstance *inst = (LegacyInstance *)m_inst;
if (!inst->shouldUpdate() || inst->shouldUseCustomBaseJar())
{
ModTheJar();
}
else
{
emitSucceeded();
}
}
else
{
*/
fmllibsStart();
//}
}
void LegacyUpdate::fmllibsStart()
@ -415,65 +398,6 @@ void LegacyUpdate::jarFailed()
emitFailed("Failed to download the minecraft jar. Try again later.");
}
bool LegacyUpdate::MergeZipFiles(QuaZip *into, QFileInfo from, QSet<QString> &contained,
MetainfAction metainf)
{
setStatus(tr("Installing mods: Adding ") + from.fileName() + " ...");
QuaZip modZip(from.filePath());
modZip.open(QuaZip::mdUnzip);
QuaZipFile fileInsideMod(&modZip);
QuaZipFile zipOutFile(into);
for (bool more = modZip.goToFirstFile(); more; more = modZip.goToNextFile())
{
QString filename = modZip.getCurrentFileName();
if (filename.contains("META-INF") && metainf == LegacyUpdate::IgnoreMetainf)
{
QLOG_INFO() << "Skipping META-INF " << filename << " from " << from.fileName();
continue;
}
if (contained.contains(filename))
{
QLOG_INFO() << "Skipping already contained file " << filename << " from "
<< from.fileName();
continue;
}
contained.insert(filename);
QLOG_INFO() << "Adding file " << filename << " from " << from.fileName();
if (!fileInsideMod.open(QIODevice::ReadOnly))
{
QLOG_ERROR() << "Failed to open " << filename << " from " << from.fileName();
return false;
}
/*
QuaZipFileInfo old_info;
fileInsideMod.getFileInfo(&old_info);
*/
QuaZipNewInfo info_out(fileInsideMod.getActualFileName());
/*
info_out.externalAttr = old_info.externalAttr;
*/
if (!zipOutFile.open(QIODevice::WriteOnly, info_out))
{
QLOG_ERROR() << "Failed to open " << filename << " in the jar";
fileInsideMod.close();
return false;
}
if (!JlCompress::copyData(fileInsideMod, zipOutFile))
{
zipOutFile.close();
fileInsideMod.close();
QLOG_ERROR() << "Failed to copy data of " << filename << " into the jar";
return false;
}
zipOutFile.close();
fileInsideMod.close();
}
return true;
}
void LegacyUpdate::ModTheJar()
{
LegacyInstance *inst = (LegacyInstance *)m_inst;
@ -531,85 +455,13 @@ void LegacyUpdate::ModTheJar()
// TaskStep(); // STEP 1
setStatus(tr("Installing mods: Opening minecraft.jar ..."));
QuaZip zipOut(runnableJar.filePath());
if (!zipOut.open(QuaZip::mdCreate))
const auto & mods = modList->allMods();
QString outputJarPath = runnableJar.filePath();
QString inputJarPath = baseJar.filePath();
if(!JarUtils::createModdedJar(inputJarPath, outputJarPath, mods))
{
QFile::remove(runnableJar.filePath());
emitFailed("Failed to open the minecraft.jar for modding");
return;
}
// Files already added to the jar.
// These files will be skipped.
QSet<QString> addedFiles;
// Modify the jar
setStatus(tr("Installing mods: Adding mod files..."));
for (int i = modList->size() - 1; i >= 0; i--)
{
auto &mod = modList->operator[](i);
// do not merge disabled mods.
if (!mod.enabled())
continue;
if (mod.type() == Mod::MOD_ZIPFILE)
{
if (!MergeZipFiles(&zipOut, mod.filename(), addedFiles, LegacyUpdate::KeepMetainf))
{
zipOut.close();
QFile::remove(runnableJar.filePath());
emitFailed("Failed to add " + mod.filename().fileName() + " to the jar.");
return;
}
}
else if (mod.type() == Mod::MOD_SINGLEFILE)
{
auto filename = mod.filename();
if (!JlCompress::compressFile(&zipOut, filename.absoluteFilePath(),
filename.fileName()))
{
zipOut.close();
QFile::remove(runnableJar.filePath());
emitFailed("Failed to add " + filename.fileName() + " to the jar");
return;
}
addedFiles.insert(filename.fileName());
QLOG_INFO() << "Adding file " << filename.fileName() << " from "
<< filename.absoluteFilePath();
}
else if (mod.type() == Mod::MOD_FOLDER)
{
auto filename = mod.filename();
QString what_to_zip = filename.absoluteFilePath();
QDir dir(what_to_zip);
dir.cdUp();
QString parent_dir = dir.absolutePath();
if (!JlCompress::compressSubDir(&zipOut, what_to_zip, parent_dir, true, addedFiles))
{
zipOut.close();
QFile::remove(runnableJar.filePath());
emitFailed("Failed to add " + filename.fileName() + " to the jar");
return;
}
QLOG_INFO() << "Adding folder " << filename.fileName() << " from "
<< filename.absoluteFilePath();
}
}
if (!MergeZipFiles(&zipOut, baseJar, addedFiles, LegacyUpdate::IgnoreMetainf))
{
zipOut.close();
QFile::remove(runnableJar.filePath());
emitFailed("Failed to insert minecraft.jar contents.");
return;
}
// Recompress the jar
zipOut.close();
if (zipOut.getZipError() != 0)
{
QFile::remove(runnableJar.filePath());
emitFailed("Failed to finalize minecraft.jar!");
emitFailed(tr("Failed to create the custom Minecraft jar file."));
return;
}
inst->setShouldRebuild(false);

View File

@ -53,15 +53,6 @@ slots:
void ModTheJar();
private:
enum MetainfAction
{
KeepMetainf, // the META-INF folder will be added from the merged jar
IgnoreMetainf // the META-INF from the merged jar will be ignored
};
bool MergeZipFiles(QuaZip *into, QFileInfo from, QSet<QString> &contained,
MetainfAction metainf);
private:
std::shared_ptr<QNetworkReply> m_reply;

View File

@ -126,6 +126,11 @@ public:
return m_dir;
}
const QList<Mod> & allMods()
{
return mods;
}
private:
void internalSort(QList<Mod> & what);
struct OrderItem

View File

@ -6,7 +6,6 @@
#include "tasks/SequentialTask.h"
#include "forge/ForgeInstaller.h"
#include "forge/ForgeVersionList.h"
#include "OneSixInstance_p.h"
#include "MultiMC.h"
#include "pathutils.h"

View File

@ -21,7 +21,6 @@
#include "logic/OneSixInstance.h"
#include "logic/OneSixInstance_p.h"
#include "logic/OneSixUpdate.h"
#include "logic/minecraft/InstanceVersion.h"
#include "minecraft/VersionBuildError.h"
@ -39,13 +38,11 @@
#include "gui/pages/ScreenshotsPage.h"
#include "gui/pages/OtherLogsPage.h"
OneSixInstance::OneSixInstance(const QString &rootDir, SettingsObject *settings,
QObject *parent)
: BaseInstance(new OneSixInstancePrivate(), rootDir, settings, parent)
OneSixInstance::OneSixInstance(const QString &rootDir, SettingsObject *settings, QObject *parent)
: BaseInstance(rootDir, settings, parent)
{
I_D(OneSixInstance);
d->m_settings->registerSetting("IntendedVersion", "");
d->version.reset(new InstanceVersion(this, this));
m_settings->registerSetting("IntendedVersion", "");
version.reset(new InstanceVersion(this, this));
}
void OneSixInstance::init()
@ -184,8 +181,6 @@ QDir OneSixInstance::reconstructAssets(std::shared_ptr<InstanceVersion> version)
QStringList OneSixInstance::processMinecraftArgs(AuthSessionPtr session)
{
I_D(OneSixInstance);
auto version = d->version;
QString args_pattern = version->minecraftArguments;
for (auto tweaker : version->tweakers)
{
@ -207,7 +202,7 @@ QStringList OneSixInstance::processMinecraftArgs(AuthSessionPtr session)
QString absRootDir = QDir(minecraftRoot()).absolutePath();
token_mapping["game_directory"] = absRootDir;
QString absAssetsDir = QDir("assets/").absolutePath();
token_mapping["game_assets"] = reconstructAssets(d->version).absolutePath();
token_mapping["game_assets"] = reconstructAssets(version).absolutePath();
token_mapping["user_properties"] = session->serializeUserProperties();
token_mapping["user_type"] = session->user_type;
@ -225,13 +220,11 @@ QStringList OneSixInstance::processMinecraftArgs(AuthSessionPtr session)
bool OneSixInstance::prepareForLaunch(AuthSessionPtr session, QString &launchScript)
{
I_D(OneSixInstance);
QIcon icon = MMC->icons()->getIcon(iconKey());
auto pixmap = icon.pixmap(128, 128);
pixmap.save(PathCombine(minecraftRoot(), "icon.png"), "PNG");
auto version = d->version;
if (!version)
return nullptr;
@ -242,20 +235,15 @@ bool OneSixInstance::prepareForLaunch(AuthSessionPtr session, QString &launchScr
{
launchScript += "cp " + librariesPath().absoluteFilePath(lib->storagePath()) + "\n";
}
QString minecraftjarpath;
if (version->hasJarMods())
{
for (auto jarmod : version->jarMods)
{
launchScript += "cp " + jarmodsPath().absoluteFilePath(jarmod->name) + "\n";
}
minecraftjarpath = version->id + "/" + version->id + "-stripped.jar";
launchScript += "cp " + QDir(instanceRoot()).absoluteFilePath("temp.jar") + "\n";
}
else
{
minecraftjarpath = version->id + "/" + version->id + ".jar";
QString relpath = version->id + "/" + version->id + ".jar";
launchScript += "cp " + versionsPath().absoluteFilePath(relpath) + "\n";
}
launchScript += "cp " + versionsPath().absoluteFilePath(minecraftjarpath) + "\n";
}
if (!version->mainClass.isEmpty())
{
@ -320,46 +308,42 @@ void OneSixInstance::cleanupAfterRun()
std::shared_ptr<ModList> OneSixInstance::loaderModList()
{
I_D(OneSixInstance);
if (!d->loader_mod_list)
if (!loader_mod_list)
{
d->loader_mod_list.reset(new ModList(loaderModsDir()));
loader_mod_list.reset(new ModList(loaderModsDir()));
}
d->loader_mod_list->update();
return d->loader_mod_list;
loader_mod_list->update();
return loader_mod_list;
}
std::shared_ptr<ModList> OneSixInstance::coreModList()
{
I_D(OneSixInstance);
if (!d->core_mod_list)
if (!core_mod_list)
{
d->core_mod_list.reset(new ModList(coreModsDir()));
core_mod_list.reset(new ModList(coreModsDir()));
}
d->core_mod_list->update();
return d->core_mod_list;
core_mod_list->update();
return core_mod_list;
}
std::shared_ptr<ModList> OneSixInstance::resourcePackList()
{
I_D(OneSixInstance);
if (!d->resource_pack_list)
if (!resource_pack_list)
{
d->resource_pack_list.reset(new ModList(resourcePacksDir()));
resource_pack_list.reset(new ModList(resourcePacksDir()));
}
d->resource_pack_list->update();
return d->resource_pack_list;
resource_pack_list->update();
return resource_pack_list;
}
std::shared_ptr<ModList> OneSixInstance::texturePackList()
{
I_D(OneSixInstance);
if (!d->texture_pack_list)
if (!texture_pack_list)
{
d->texture_pack_list.reset(new ModList(texturePacksDir()));
texture_pack_list.reset(new ModList(texturePacksDir()));
}
d->texture_pack_list->update();
return d->texture_pack_list;
texture_pack_list->update();
return texture_pack_list;
}
bool OneSixInstance::setIntendedVersionId(QString version)
@ -386,22 +370,18 @@ bool OneSixInstance::shouldUpdate() const
bool OneSixInstance::versionIsCustom()
{
I_D(const OneSixInstance);
auto ver = d->version;
if (ver)
if (version)
{
return !ver->isVanilla();
return !version->isVanilla();
}
return false;
}
bool OneSixInstance::versionIsFTBPack()
{
I_D(const OneSixInstance);
auto ver = d->version;
if (ver)
if (version)
{
return ver->hasFtbPack();
return version->hasFtbPack();
}
return false;
}
@ -413,11 +393,10 @@ QString OneSixInstance::currentVersionId() const
void OneSixInstance::reloadVersion()
{
I_D(OneSixInstance);
try
{
d->version->reload(externalPatches());
version->reload(externalPatches());
unsetFlag(VersionBrokenFlag);
emit versionReloaded();
}
@ -426,7 +405,7 @@ void OneSixInstance::reloadVersion()
}
catch (MMCError &error)
{
d->version->clear();
version->clear();
setFlag(VersionBrokenFlag);
// TODO: rethrow to show some error message(s)?
emit versionReloaded();
@ -436,25 +415,13 @@ void OneSixInstance::reloadVersion()
void OneSixInstance::clearVersion()
{
I_D(OneSixInstance);
d->version->clear();
version->clear();
emit versionReloaded();
}
std::shared_ptr<InstanceVersion> OneSixInstance::getFullVersion() const
{
I_D(const OneSixInstance);
return d->version;
}
QString OneSixInstance::defaultBaseJar() const
{
return "versions/" + intendedVersionId() + "/" + intendedVersionId() + ".jar";
}
QString OneSixInstance::defaultCustomBaseJar() const
{
return PathCombine(instanceRoot(), "custom.jar");
return version;
}
QString OneSixInstance::getStatusbarDescription()

View File

@ -42,7 +42,7 @@ public:
std::shared_ptr<ModList> texturePackList() override;
virtual QSet<QString> traits();
////// Directories and files //////
QString jarModsDir() const;
QString resourcePacksDir() const;
@ -67,26 +67,23 @@ public:
/**
* reload the full version json files.
*
*
* throws various exceptions :3
*/
void reloadVersion();
/// clears all version information in preparation for an update
void clearVersion();
/// get the current full version info
std::shared_ptr<InstanceVersion> getFullVersion() const;
/// is the current version original, or custom?
virtual bool versionIsCustom() override;
/// does this instance have an FTB pack patch inside?
bool versionIsFTBPack();
virtual QString defaultBaseJar() const override;
virtual QString defaultCustomBaseJar() const override;
virtual QString getStatusbarDescription() override;
virtual QDir jarmodsPath() const;
@ -107,6 +104,14 @@ signals:
private:
QStringList processMinecraftArgs(AuthSessionPtr account);
QDir reconstructAssets(std::shared_ptr<InstanceVersion> version);
protected:
std::shared_ptr<InstanceVersion> version;
std::shared_ptr<ModList> jar_mod_list;
std::shared_ptr<ModList> loader_mod_list;
std::shared_ptr<ModList> core_mod_list;
std::shared_ptr<ModList> resource_pack_list;
std::shared_ptr<ModList> texture_pack_list;
};
Q_DECLARE_METATYPE(std::shared_ptr<OneSixInstance>)

View File

@ -1,33 +0,0 @@
/* Copyright 2013-2014 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include "logic/BaseInstance_p.h"
class ModList;
class InstanceVersion;
class OneSixInstancePrivate : public BaseInstancePrivate
{
public:
virtual ~OneSixInstancePrivate() {};
std::shared_ptr<InstanceVersion> version;
std::shared_ptr<ModList> jar_mod_list;
std::shared_ptr<ModList> loader_mod_list;
std::shared_ptr<ModList> core_mod_list;
std::shared_ptr<ModList> resource_pack_list;
std::shared_ptr<ModList> texture_pack_list;
};

View File

@ -33,6 +33,7 @@
#include "logic/forge/ForgeMirrors.h"
#include "logic/net/URLConstants.h"
#include "logic/assets/AssetsUtils.h"
#include "JarUtils.h"
OneSixUpdate::OneSixUpdate(OneSixInstance *inst, QObject *parent) : Task(parent), m_inst(inst)
{
@ -287,23 +288,44 @@ void OneSixUpdate::jarlibFinished()
OneSixInstance *inst = (OneSixInstance *)m_inst;
std::shared_ptr<InstanceVersion> version = inst->getFullVersion();
// nuke obsolete stripped jar(s) if needed
QString version_id = version->id;
QString strippedPath = version_id + "/" + version_id + "-stripped.jar";
QFile strippedJar(strippedPath);
if(strippedJar.exists())
{
strippedJar.remove();
}
auto finalJarPath = QDir(m_inst->instanceRoot()).absoluteFilePath("temp.jar");
QFile finalJar(finalJarPath);
if(finalJar.exists())
{
if(!finalJar.remove())
{
emitFailed(tr("Couldn't remove stale jar file: %1").arg(finalJarPath));
return;
}
}
// create stripped jar, if needed
if (version->hasJarMods())
{
// FIXME: good candidate for moving elsewhere (jar location resolving/version caching).
QString version_id = version->id;
auto sourceJarPath = m_inst->versionsPath().absoluteFilePath(version->id + "/" + version->id + ".jar");
QString localPath = version_id + "/" + version_id + ".jar";
QString strippedPath = version_id + "/" + version_id + "-stripped.jar";
auto metacache = MMC->metacache();
auto entry = metacache->resolveEntry("versions", localPath);
auto entryStripped = metacache->resolveEntry("versions", strippedPath);
QString fullJarPath = entry->getFullPath();
QString fullStrippedJarPath = entryStripped->getFullPath();
QFileInfo finfo(fullStrippedJarPath);
if (entry->md5sum != jarHashOnEntry || !finfo.exists())
//FIXME: remove need to convert to different objects here
QList<Mod> mods;
for (auto jarmod : version->jarMods)
{
stripJar(fullJarPath, fullStrippedJarPath);
QString filePath = m_inst->jarmodsPath().absoluteFilePath(jarmod->name);
mods.push_back(Mod(QFileInfo(filePath)));
}
if(!JarUtils::createModdedJar(sourceJarPath, finalJarPath, mods))
{
emitFailed(tr("Failed to create the custom Minecraft jar file."));
return;
}
}
if (version->traits.contains("legacyFML"))
@ -324,87 +346,6 @@ void OneSixUpdate::jarlibFailed()
tr("Failed to download the following files:\n%1\n\nPlease try again.").arg(failed_all));
}
void OneSixUpdate::stripJar(QString origPath, QString newPath)
{
QFileInfo runnableJar(newPath);
if (runnableJar.exists() && !QFile::remove(runnableJar.filePath()))
{
emitFailed("Failed to delete old minecraft.jar");
return;
}
// TaskStep(); // STEP 1
setStatus(tr("Creating stripped jar: Opening minecraft.jar ..."));
QuaZip zipOut(runnableJar.filePath());
if (!zipOut.open(QuaZip::mdCreate))
{
QFile::remove(runnableJar.filePath());
emitFailed("Failed to open the minecraft.jar for stripping");
return;
}
// Modify the jar
setStatus(tr("Creating stripped jar: Adding files..."));
if (!MergeZipFiles(&zipOut, origPath))
{
zipOut.close();
QFile::remove(runnableJar.filePath());
emitFailed("Failed to add " + origPath + " to the jar.");
return;
}
}
bool OneSixUpdate::MergeZipFiles(QuaZip *into, QString from)
{
setStatus(tr("Installing mods: Adding ") + from + " ...");
QuaZip modZip(from);
modZip.open(QuaZip::mdUnzip);
QuaZipFile fileInsideMod(&modZip);
QuaZipFile zipOutFile(into);
for (bool more = modZip.goToFirstFile(); more; more = modZip.goToNextFile())
{
QString filename = modZip.getCurrentFileName();
if (filename.contains("META-INF"))
{
QLOG_INFO() << "Skipping META-INF " << filename << " from " << from;
continue;
}
QLOG_INFO() << "Adding file " << filename << " from " << from;
if (!fileInsideMod.open(QIODevice::ReadOnly))
{
QLOG_ERROR() << "Failed to open " << filename << " from " << from;
return false;
}
/*
QuaZipFileInfo old_info;
fileInsideMod.getFileInfo(&old_info);
*/
QuaZipNewInfo info_out(fileInsideMod.getActualFileName());
/*
info_out.externalAttr = old_info.externalAttr;
*/
if (!zipOutFile.open(QIODevice::WriteOnly, info_out))
{
QLOG_ERROR() << "Failed to open " << filename << " in the jar";
fileInsideMod.close();
return false;
}
if (!JlCompress::copyData(fileInsideMod, zipOutFile))
{
zipOutFile.close();
fileInsideMod.close();
QLOG_ERROR() << "Failed to copy data of " << filename << " into the jar";
return false;
}
zipOutFile.close();
fileInsideMod.close();
}
return true;
}
void OneSixUpdate::fmllibsStart()
{
// Get the mod list

View File

@ -53,8 +53,6 @@ slots:
void assetsFinished();
void assetsFailed();
void stripJar(QString origPath, QString newPath);
bool MergeZipFiles(QuaZip *into, QString from);
private:
NetJobPtr jarlibDownloadJob;
NetJobPtr legacyDownloadJob;
@ -63,7 +61,7 @@ private:
std::shared_ptr<MinecraftVersion> targetVersion;
/// the task that is spawned for version updates
std::shared_ptr<Task> versionUpdateTask;
OneSixInstance *m_inst = nullptr;
QString jarHashOnEntry;
QList<FMLlib> fmlLibsToProcess;

View File

@ -1,98 +0,0 @@
#include "URNResolver.h"
#include <logger/QsLog.h>
#include "MultiMC.h"
#include "logic/forge/ForgeVersionList.h"
#include "logic/forge/ForgeVersion.h"
QString unescapeNSS(QString RawNSS)
{
QString NSS;
NSS.reserve(RawNSS.size());
enum
{
Normal,
FirstHex,
SecondHex
} ParseState = Normal;
QByteArray translator(" ");
for (auto ch : RawNSS)
{
if(ParseState == Normal)
{
if(ch == '%')
{
ParseState = FirstHex;
continue;
}
else
{
NSS.append(ch);
}
}
if(ParseState == FirstHex)
{
translator[0] = ch.toLower().unicode();
ParseState = SecondHex;
}
else if(ParseState == SecondHex)
{
translator[1] = ch.toLower().unicode();
auto result = QByteArray::fromHex(translator);
if (result[0] == '\0')
return NSS;
NSS.append(result);
ParseState = Normal;
}
}
return NSS;
}
bool URNResolver::parse(const QString &URN, QString &NID, QString &NSS)
{
QRegExp URNPattern(
"^urn:([a-z0-9][a-z0-9-]{0,31}):(([a-z0-9()+,\\-.:=@;$_!*']|%[0-9a-f]{2})+).*",
Qt::CaseInsensitive);
if (URNPattern.indexIn(URN) == -1)
return false;
auto captures = URNPattern.capturedTexts();
QString RawNID = captures[1];
QString RawNSS = captures[2];
NID = RawNID.toLower();
NSS = unescapeNSS(RawNSS);
return true;
}
URNResolver::URNResolver()
{
}
QVariant URNResolver::resolve(QString URN)
{
QString NID, NSS;
parse(URN, NID, NSS);
if(NID != "x-mmc")
return QVariant();
auto parts = NSS.split(":");
if(parts.size() < 1)
return QVariant();
unsigned int version = parts[0].toUInt();
switch(version)
{
case 1:
return resolveV1(parts.mid(1));
default:
return QVariant();
}
}
/**
* TODO: implement.
*/
QVariant URNResolver::resolveV1(QStringList parts)
{
return QVariant();
}

View File

@ -1,18 +0,0 @@
#pragma once
#include <QString>
#include <QMap>
#include <memory>
#include <QVariant>
class URNResolver;
typedef std::shared_ptr<URNResolver> URNResolverPtr;
class URNResolver
{
public:
URNResolver();
QVariant resolve (QString URN);
static bool parse (const QString &URN, QString &NID, QString &NSS);
private:
QVariant resolveV1 (QStringList parts);
};

View File

@ -43,6 +43,7 @@ VersionFilePtr VersionFile::fromJson(const QJsonDocument &doc, const QString &fi
}
if (!doc.isObject())
{
throw JSONValidationError(filename + " is not an object");
}
QJsonObject root = doc.object();