NOISSUE Fix jar mods for OnesSix
This commit is contained in:
parent
01f44e0f39
commit
a30a9559c7
@ -380,7 +380,6 @@ 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
|
||||
@ -391,15 +390,9 @@ SET(MULTIMC_SOURCES
|
||||
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
|
||||
@ -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
|
||||
|
31
MultiMC.cpp
31
MultiMC.cpp
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
@ -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);
|
@ -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
|
||||
|
@ -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;
|
||||
@ -131,26 +130,6 @@ public:
|
||||
/// 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>)
|
||||
|
@ -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;
|
||||
};
|
@ -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
|
||||
|
@ -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();
|
||||
}
|
@ -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
161
logic/JarUtils.cpp
Normal 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
18
logic/JarUtils.h
Normal 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);
|
||||
}
|
@ -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)
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
};
|
@ -30,6 +30,7 @@
|
||||
|
||||
#include "logger/QsLog.h"
|
||||
#include "logic/net/URLConstants.h"
|
||||
#include "JarUtils.h"
|
||||
|
||||
|
||||
LegacyUpdate::LegacyUpdate(BaseInstance *inst, QObject *parent) : Task(parent), m_inst(inst)
|
||||
@ -38,25 +39,7 @@ LegacyUpdate::LegacyUpdate(BaseInstance *inst, QObject *parent) : Task(parent),
|
||||
|
||||
void LegacyUpdate::executeTask()
|
||||
{
|
||||
/*
|
||||
if(m_only_prepare)
|
||||
{
|
||||
// FIXME: think this through some more.
|
||||
LegacyInstance *inst = (LegacyInstance *)m_inst;
|
||||
if (!inst->shouldUpdate() || inst->shouldUseCustomBaseJar())
|
||||
{
|
||||
ModTheJar();
|
||||
}
|
||||
else
|
||||
{
|
||||
emitSucceeded();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*/
|
||||
fmllibsStart();
|
||||
//}
|
||||
}
|
||||
|
||||
void LegacyUpdate::fmllibsStart()
|
||||
@ -415,65 +398,6 @@ void LegacyUpdate::jarFailed()
|
||||
emitFailed("Failed to download the minecraft jar. Try again later.");
|
||||
}
|
||||
|
||||
bool LegacyUpdate::MergeZipFiles(QuaZip *into, QFileInfo from, QSet<QString> &contained,
|
||||
MetainfAction metainf)
|
||||
{
|
||||
setStatus(tr("Installing mods: Adding ") + from.fileName() + " ...");
|
||||
|
||||
QuaZip modZip(from.filePath());
|
||||
modZip.open(QuaZip::mdUnzip);
|
||||
|
||||
QuaZipFile fileInsideMod(&modZip);
|
||||
QuaZipFile zipOutFile(into);
|
||||
for (bool more = modZip.goToFirstFile(); more; more = modZip.goToNextFile())
|
||||
{
|
||||
QString filename = modZip.getCurrentFileName();
|
||||
if (filename.contains("META-INF") && metainf == LegacyUpdate::IgnoreMetainf)
|
||||
{
|
||||
QLOG_INFO() << "Skipping META-INF " << filename << " from " << from.fileName();
|
||||
continue;
|
||||
}
|
||||
if (contained.contains(filename))
|
||||
{
|
||||
QLOG_INFO() << "Skipping already contained file " << filename << " from "
|
||||
<< from.fileName();
|
||||
continue;
|
||||
}
|
||||
contained.insert(filename);
|
||||
QLOG_INFO() << "Adding file " << filename << " from " << from.fileName();
|
||||
|
||||
if (!fileInsideMod.open(QIODevice::ReadOnly))
|
||||
{
|
||||
QLOG_ERROR() << "Failed to open " << filename << " from " << from.fileName();
|
||||
return false;
|
||||
}
|
||||
/*
|
||||
QuaZipFileInfo old_info;
|
||||
fileInsideMod.getFileInfo(&old_info);
|
||||
*/
|
||||
QuaZipNewInfo info_out(fileInsideMod.getActualFileName());
|
||||
/*
|
||||
info_out.externalAttr = old_info.externalAttr;
|
||||
*/
|
||||
if (!zipOutFile.open(QIODevice::WriteOnly, info_out))
|
||||
{
|
||||
QLOG_ERROR() << "Failed to open " << filename << " in the jar";
|
||||
fileInsideMod.close();
|
||||
return false;
|
||||
}
|
||||
if (!JlCompress::copyData(fileInsideMod, zipOutFile))
|
||||
{
|
||||
zipOutFile.close();
|
||||
fileInsideMod.close();
|
||||
QLOG_ERROR() << "Failed to copy data of " << filename << " into the jar";
|
||||
return false;
|
||||
}
|
||||
zipOutFile.close();
|
||||
fileInsideMod.close();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void LegacyUpdate::ModTheJar()
|
||||
{
|
||||
LegacyInstance *inst = (LegacyInstance *)m_inst;
|
||||
@ -531,85 +455,13 @@ void LegacyUpdate::ModTheJar()
|
||||
// TaskStep(); // STEP 1
|
||||
setStatus(tr("Installing mods: Opening minecraft.jar ..."));
|
||||
|
||||
QuaZip zipOut(runnableJar.filePath());
|
||||
if (!zipOut.open(QuaZip::mdCreate))
|
||||
{
|
||||
QFile::remove(runnableJar.filePath());
|
||||
emitFailed("Failed to open the minecraft.jar for modding");
|
||||
return;
|
||||
}
|
||||
// Files already added to the jar.
|
||||
// These files will be skipped.
|
||||
QSet<QString> addedFiles;
|
||||
const auto & mods = modList->allMods();
|
||||
QString outputJarPath = runnableJar.filePath();
|
||||
QString inputJarPath = baseJar.filePath();
|
||||
|
||||
// Modify the jar
|
||||
setStatus(tr("Installing mods: Adding mod files..."));
|
||||
for (int i = modList->size() - 1; i >= 0; i--)
|
||||
if(!JarUtils::createModdedJar(inputJarPath, outputJarPath, mods))
|
||||
{
|
||||
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);
|
||||
|
@ -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;
|
||||
|
@ -126,6 +126,11 @@ public:
|
||||
return m_dir;
|
||||
}
|
||||
|
||||
const QList<Mod> & allMods()
|
||||
{
|
||||
return mods;
|
||||
}
|
||||
|
||||
private:
|
||||
void internalSort(QList<Mod> & what);
|
||||
struct OrderItem
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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()
|
||||
|
@ -84,9 +84,6 @@ public:
|
||||
/// 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>)
|
||||
|
@ -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;
|
||||
};
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
@ -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);
|
||||
};
|
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user