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/InstanceFactory.cpp
|
||||||
logic/BaseInstance.h
|
logic/BaseInstance.h
|
||||||
logic/BaseInstance.cpp
|
logic/BaseInstance.cpp
|
||||||
logic/BaseInstance_p.h
|
|
||||||
logic/Mod.h
|
logic/Mod.h
|
||||||
logic/Mod.cpp
|
logic/Mod.cpp
|
||||||
logic/ModList.h
|
logic/ModList.h
|
||||||
@ -391,15 +390,9 @@ SET(MULTIMC_SOURCES
|
|||||||
logic/VersionFilterData.cpp
|
logic/VersionFilterData.cpp
|
||||||
|
|
||||||
# Instance launch
|
# Instance launch
|
||||||
logic/InstanceLauncher.h
|
|
||||||
logic/InstanceLauncher.cpp
|
|
||||||
logic/MinecraftProcess.h
|
logic/MinecraftProcess.h
|
||||||
logic/MinecraftProcess.cpp
|
logic/MinecraftProcess.cpp
|
||||||
|
|
||||||
# URN parser/resolver
|
|
||||||
logic/URNResolver.cpp
|
|
||||||
logic/URNResolver.h
|
|
||||||
|
|
||||||
# Annoying nag screen logic
|
# Annoying nag screen logic
|
||||||
logic/NagUtils.h
|
logic/NagUtils.h
|
||||||
logic/NagUtils.cpp
|
logic/NagUtils.cpp
|
||||||
@ -476,7 +469,6 @@ SET(MULTIMC_SOURCES
|
|||||||
# legacy instances
|
# legacy instances
|
||||||
logic/LegacyInstance.h
|
logic/LegacyInstance.h
|
||||||
logic/LegacyInstance.cpp
|
logic/LegacyInstance.cpp
|
||||||
logic/LegacyInstance_p.h
|
|
||||||
logic/LegacyUpdate.h
|
logic/LegacyUpdate.h
|
||||||
logic/LegacyUpdate.cpp
|
logic/LegacyUpdate.cpp
|
||||||
|
|
||||||
@ -485,7 +477,10 @@ SET(MULTIMC_SOURCES
|
|||||||
logic/OneSixUpdate.cpp
|
logic/OneSixUpdate.cpp
|
||||||
logic/OneSixInstance.h
|
logic/OneSixInstance.h
|
||||||
logic/OneSixInstance.cpp
|
logic/OneSixInstance.cpp
|
||||||
logic/OneSixInstance_p.h
|
|
||||||
|
# Common utils for instances
|
||||||
|
logic/JarUtils.h
|
||||||
|
logic/JarUtils.cpp
|
||||||
|
|
||||||
# OneSix version json infrastructure
|
# OneSix version json infrastructure
|
||||||
logic/minecraft/GradleSpecifier.h
|
logic/minecraft/GradleSpecifier.h
|
||||||
|
31
MultiMC.cpp
31
MultiMC.cpp
@ -25,7 +25,6 @@
|
|||||||
|
|
||||||
#include "logic/status/StatusChecker.h"
|
#include "logic/status/StatusChecker.h"
|
||||||
|
|
||||||
#include "logic/InstanceLauncher.h"
|
|
||||||
#include "logic/net/HttpMetaCache.h"
|
#include "logic/net/HttpMetaCache.h"
|
||||||
#include "logic/net/URLConstants.h"
|
#include "logic/net/URLConstants.h"
|
||||||
|
|
||||||
@ -38,8 +37,6 @@
|
|||||||
#include "logic/tools/JVisualVM.h"
|
#include "logic/tools/JVisualVM.h"
|
||||||
#include "logic/tools/MCEditTool.h"
|
#include "logic/tools/MCEditTool.h"
|
||||||
|
|
||||||
#include "logic/URNResolver.h"
|
|
||||||
|
|
||||||
#include "pathutils.h"
|
#include "pathutils.h"
|
||||||
#include "cmdutils.h"
|
#include "cmdutils.h"
|
||||||
#include "logic/settings/INISettingsObject.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.addShortOpt("dir", 'd');
|
||||||
parser.addDocumentation("dir", "use the supplied directory as MultiMC root instead of "
|
parser.addDocumentation("dir", "use the supplied directory as MultiMC root instead of "
|
||||||
"the binary location (use '.' for current)");
|
"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
|
// parse the arguments
|
||||||
try
|
try
|
||||||
@ -266,18 +256,6 @@ MultiMC::MultiMC(int &argc, char **argv, bool test_mode) : QApplication(argc, ar
|
|||||||
tool->registerSettings(m_settings);
|
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()));
|
connect(this, SIGNAL(aboutToQuit()), SLOT(onExit()));
|
||||||
m_status = MultiMC::Initialized;
|
m_status = MultiMC::Initialized;
|
||||||
}
|
}
|
||||||
@ -704,15 +682,6 @@ std::shared_ptr<JavaVersionList> MultiMC::javalist()
|
|||||||
return m_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)
|
void MultiMC::installUpdates(const QString updateFilesDir, UpdateFlags flags)
|
||||||
{
|
{
|
||||||
// if we are going to update on exit, save the params now
|
// if we are going to update on exit, save the params now
|
||||||
|
@ -23,7 +23,6 @@ class NewsChecker;
|
|||||||
class StatusChecker;
|
class StatusChecker;
|
||||||
class BaseProfilerFactory;
|
class BaseProfilerFactory;
|
||||||
class BaseDetachedToolFactory;
|
class BaseDetachedToolFactory;
|
||||||
class URNResolver;
|
|
||||||
class TranslationDownloader;
|
class TranslationDownloader;
|
||||||
|
|
||||||
#if defined(MMC)
|
#if defined(MMC)
|
||||||
@ -118,8 +117,6 @@ public:
|
|||||||
|
|
||||||
std::shared_ptr<JavaVersionList> javalist();
|
std::shared_ptr<JavaVersionList> javalist();
|
||||||
|
|
||||||
std::shared_ptr<URNResolver> resolver();
|
|
||||||
|
|
||||||
QMap<QString, std::shared_ptr<BaseProfilerFactory>> profilers()
|
QMap<QString, std::shared_ptr<BaseProfilerFactory>> profilers()
|
||||||
{
|
{
|
||||||
return m_profilers;
|
return m_profilers;
|
||||||
@ -206,7 +203,6 @@ private:
|
|||||||
std::shared_ptr<LiteLoaderVersionList> m_liteloaderlist;
|
std::shared_ptr<LiteLoaderVersionList> m_liteloaderlist;
|
||||||
std::shared_ptr<MinecraftVersionList> m_minecraftlist;
|
std::shared_ptr<MinecraftVersionList> m_minecraftlist;
|
||||||
std::shared_ptr<JavaVersionList> m_javalist;
|
std::shared_ptr<JavaVersionList> m_javalist;
|
||||||
std::shared_ptr<URNResolver> m_resolver;
|
|
||||||
std::shared_ptr<TranslationDownloader> m_translationChecker;
|
std::shared_ptr<TranslationDownloader> m_translationChecker;
|
||||||
|
|
||||||
QMap<QString, std::shared_ptr<BaseProfilerFactory>> m_profilers;
|
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 "MultiMC.h"
|
||||||
#include "BaseInstance.h"
|
#include "BaseInstance.h"
|
||||||
#include "BaseInstance_p.h"
|
|
||||||
|
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
@ -31,61 +30,50 @@
|
|||||||
#include "logic/icons/IconList.h"
|
#include "logic/icons/IconList.h"
|
||||||
#include "logic/InstanceList.h"
|
#include "logic/InstanceList.h"
|
||||||
|
|
||||||
BaseInstance::BaseInstance(BaseInstancePrivate *d_in, const QString &rootDir,
|
BaseInstance::BaseInstance(const QString &rootDir, SettingsObject *settings, QObject *parent)
|
||||||
SettingsObject *settings_obj, QObject *parent)
|
: QObject(parent)
|
||||||
: QObject(parent), inst_d(d_in)
|
|
||||||
{
|
{
|
||||||
I_D(BaseInstance);
|
|
||||||
d->m_settings = std::shared_ptr<SettingsObject>(settings_obj);
|
|
||||||
d->m_rootDir = rootDir;
|
|
||||||
|
|
||||||
settings().registerSetting("name", "Unnamed Instance");
|
m_settings = std::shared_ptr<SettingsObject>(settings);
|
||||||
settings().registerSetting("iconKey", "default");
|
m_rootDir = rootDir;
|
||||||
|
|
||||||
|
m_settings->registerSetting("name", "Unnamed Instance");
|
||||||
|
m_settings->registerSetting("iconKey", "default");
|
||||||
connect(MMC->icons().get(), SIGNAL(iconUpdated(QString)), SLOT(iconUpdated(QString)));
|
connect(MMC->icons().get(), SIGNAL(iconUpdated(QString)), SLOT(iconUpdated(QString)));
|
||||||
settings().registerSetting("notes", "");
|
m_settings->registerSetting("notes", "");
|
||||||
settings().registerSetting("lastLaunchTime", 0);
|
m_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", "");
|
|
||||||
|
|
||||||
auto globalSettings = MMC->settings();
|
auto globalSettings = MMC->settings();
|
||||||
|
|
||||||
// Java Settings
|
// Java Settings
|
||||||
settings().registerSetting("OverrideJava", false);
|
m_settings->registerSetting("OverrideJava", false);
|
||||||
settings().registerSetting("OverrideJavaLocation", false);
|
m_settings->registerSetting("OverrideJavaLocation", false);
|
||||||
settings().registerSetting("OverrideJavaArgs", false);
|
m_settings->registerSetting("OverrideJavaArgs", false);
|
||||||
settings().registerOverride(globalSettings->getSetting("JavaPath"));
|
m_settings->registerOverride(globalSettings->getSetting("JavaPath"));
|
||||||
settings().registerOverride(globalSettings->getSetting("JvmArgs"));
|
m_settings->registerOverride(globalSettings->getSetting("JvmArgs"));
|
||||||
|
|
||||||
// Custom Commands
|
// Custom Commands
|
||||||
settings().registerSetting({"OverrideCommands","OverrideLaunchCmd"}, false);
|
m_settings->registerSetting({"OverrideCommands","OverrideLaunchCmd"}, false);
|
||||||
settings().registerOverride(globalSettings->getSetting("PreLaunchCommand"));
|
m_settings->registerOverride(globalSettings->getSetting("PreLaunchCommand"));
|
||||||
settings().registerOverride(globalSettings->getSetting("PostExitCommand"));
|
m_settings->registerOverride(globalSettings->getSetting("PostExitCommand"));
|
||||||
|
|
||||||
// Window Size
|
// Window Size
|
||||||
settings().registerSetting("OverrideWindow", false);
|
m_settings->registerSetting("OverrideWindow", false);
|
||||||
settings().registerOverride(globalSettings->getSetting("LaunchMaximized"));
|
m_settings->registerOverride(globalSettings->getSetting("LaunchMaximized"));
|
||||||
settings().registerOverride(globalSettings->getSetting("MinecraftWinWidth"));
|
m_settings->registerOverride(globalSettings->getSetting("MinecraftWinWidth"));
|
||||||
settings().registerOverride(globalSettings->getSetting("MinecraftWinHeight"));
|
m_settings->registerOverride(globalSettings->getSetting("MinecraftWinHeight"));
|
||||||
|
|
||||||
// Memory
|
// Memory
|
||||||
settings().registerSetting("OverrideMemory", false);
|
m_settings->registerSetting("OverrideMemory", false);
|
||||||
settings().registerOverride(globalSettings->getSetting("MinMemAlloc"));
|
m_settings->registerOverride(globalSettings->getSetting("MinMemAlloc"));
|
||||||
settings().registerOverride(globalSettings->getSetting("MaxMemAlloc"));
|
m_settings->registerOverride(globalSettings->getSetting("MaxMemAlloc"));
|
||||||
settings().registerOverride(globalSettings->getSetting("PermGen"));
|
m_settings->registerOverride(globalSettings->getSetting("PermGen"));
|
||||||
|
|
||||||
// Console
|
// Console
|
||||||
settings().registerSetting("OverrideConsole", false);
|
m_settings->registerSetting("OverrideConsole", false);
|
||||||
settings().registerOverride(globalSettings->getSetting("ShowConsole"));
|
m_settings->registerOverride(globalSettings->getSetting("ShowConsole"));
|
||||||
settings().registerOverride(globalSettings->getSetting("AutoCloseConsole"));
|
m_settings->registerOverride(globalSettings->getSetting("AutoCloseConsole"));
|
||||||
settings().registerOverride(globalSettings->getSetting("LogPrePostOutput"));
|
m_settings->registerOverride(globalSettings->getSetting("LogPrePostOutput"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseInstance::iconUpdated(QString key)
|
void BaseInstance::iconUpdated(QString key)
|
||||||
@ -109,26 +97,22 @@ QString BaseInstance::id() const
|
|||||||
|
|
||||||
bool BaseInstance::isRunning() const
|
bool BaseInstance::isRunning() const
|
||||||
{
|
{
|
||||||
I_D(BaseInstance);
|
return m_isRunning;
|
||||||
return d->m_isRunning;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseInstance::setRunning(bool running) const
|
void BaseInstance::setRunning(bool running)
|
||||||
{
|
{
|
||||||
I_D(BaseInstance);
|
m_isRunning = running;
|
||||||
d->m_isRunning = running;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString BaseInstance::instanceType() const
|
QString BaseInstance::instanceType() const
|
||||||
{
|
{
|
||||||
I_D(BaseInstance);
|
return m_settings->get("InstanceType").toString();
|
||||||
return d->m_settings->get("InstanceType").toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString BaseInstance::instanceRoot() const
|
QString BaseInstance::instanceRoot() const
|
||||||
{
|
{
|
||||||
I_D(BaseInstance);
|
return m_rootDir;
|
||||||
return d->m_rootDir;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString BaseInstance::minecraftRoot() const
|
QString BaseInstance::minecraftRoot() const
|
||||||
@ -159,36 +143,34 @@ std::shared_ptr<BaseVersionList> BaseInstance::versionList() const
|
|||||||
|
|
||||||
SettingsObject &BaseInstance::settings() const
|
SettingsObject &BaseInstance::settings() const
|
||||||
{
|
{
|
||||||
I_D(BaseInstance);
|
return *m_settings;
|
||||||
return *d->m_settings;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BaseInstance::InstanceFlags BaseInstance::flags() const
|
BaseInstance::InstanceFlags BaseInstance::flags() const
|
||||||
{
|
{
|
||||||
I_D(const BaseInstance);
|
return m_flags;
|
||||||
return d->m_flags;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseInstance::setFlags(const InstanceFlags &flags)
|
void BaseInstance::setFlags(const InstanceFlags &flags)
|
||||||
{
|
{
|
||||||
I_D(BaseInstance);
|
if (flags != m_flags)
|
||||||
if (flags != d->m_flags)
|
|
||||||
{
|
{
|
||||||
d->m_flags = flags;
|
m_flags = flags;
|
||||||
emit flagsChanged();
|
emit flagsChanged();
|
||||||
emit propertiesChanged(this);
|
emit propertiesChanged(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseInstance::setFlag(const BaseInstance::InstanceFlag flag)
|
void BaseInstance::setFlag(const BaseInstance::InstanceFlag flag)
|
||||||
{
|
{
|
||||||
I_D(BaseInstance);
|
m_flags |= flag;
|
||||||
d->m_flags |= flag;
|
|
||||||
emit flagsChanged();
|
emit flagsChanged();
|
||||||
emit propertiesChanged(this);
|
emit propertiesChanged(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseInstance::unsetFlag(const BaseInstance::InstanceFlag flag)
|
void BaseInstance::unsetFlag(const BaseInstance::InstanceFlag flag)
|
||||||
{
|
{
|
||||||
I_D(BaseInstance);
|
m_flags &= ~flag;
|
||||||
d->m_flags &= ~flag;
|
|
||||||
emit flagsChanged();
|
emit flagsChanged();
|
||||||
emit propertiesChanged(this);
|
emit propertiesChanged(this);
|
||||||
}
|
}
|
||||||
@ -200,69 +182,23 @@ bool BaseInstance::canLaunch() const
|
|||||||
|
|
||||||
bool BaseInstance::reload()
|
bool BaseInstance::reload()
|
||||||
{
|
{
|
||||||
return settings().reload();
|
return m_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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
qint64 BaseInstance::lastLaunch() const
|
qint64 BaseInstance::lastLaunch() const
|
||||||
{
|
{
|
||||||
I_D(BaseInstance);
|
return m_settings->get("lastLaunchTime").value<qint64>();
|
||||||
return d->m_settings->get("lastLaunchTime").value<qint64>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseInstance::setLastLaunch(qint64 val)
|
void BaseInstance::setLastLaunch(qint64 val)
|
||||||
{
|
{
|
||||||
I_D(BaseInstance);
|
m_settings->set("lastLaunchTime", val);
|
||||||
d->m_settings->set("lastLaunchTime", val);
|
|
||||||
emit propertiesChanged(this);
|
emit propertiesChanged(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseInstance::setGroupInitial(QString val)
|
void BaseInstance::setGroupInitial(QString val)
|
||||||
{
|
{
|
||||||
I_D(BaseInstance);
|
m_group = val;
|
||||||
d->m_group = val;
|
|
||||||
emit propertiesChanged(this);
|
emit propertiesChanged(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -274,44 +210,39 @@ void BaseInstance::setGroupPost(QString val)
|
|||||||
|
|
||||||
QString BaseInstance::group() const
|
QString BaseInstance::group() const
|
||||||
{
|
{
|
||||||
I_D(BaseInstance);
|
return m_group;
|
||||||
return d->m_group;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseInstance::setNotes(QString val)
|
void BaseInstance::setNotes(QString val)
|
||||||
{
|
{
|
||||||
I_D(BaseInstance);
|
m_settings->set("notes", val);
|
||||||
d->m_settings->set("notes", val);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString BaseInstance::notes() const
|
QString BaseInstance::notes() const
|
||||||
{
|
{
|
||||||
I_D(BaseInstance);
|
return m_settings->get("notes").toString();
|
||||||
return d->m_settings->get("notes").toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseInstance::setIconKey(QString val)
|
void BaseInstance::setIconKey(QString val)
|
||||||
{
|
{
|
||||||
I_D(BaseInstance);
|
m_settings->set("iconKey", val);
|
||||||
d->m_settings->set("iconKey", val);
|
|
||||||
emit propertiesChanged(this);
|
emit propertiesChanged(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString BaseInstance::iconKey() const
|
QString BaseInstance::iconKey() const
|
||||||
{
|
{
|
||||||
I_D(BaseInstance);
|
return m_settings->get("iconKey").toString();
|
||||||
return d->m_settings->get("iconKey").toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseInstance::setName(QString val)
|
void BaseInstance::setName(QString val)
|
||||||
{
|
{
|
||||||
I_D(BaseInstance);
|
m_settings->set("name", val);
|
||||||
d->m_settings->set("name", val);
|
|
||||||
emit propertiesChanged(this);
|
emit propertiesChanged(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString BaseInstance::name() const
|
QString BaseInstance::name() const
|
||||||
{
|
{
|
||||||
I_D(BaseInstance);
|
return m_settings->get("name").toString();
|
||||||
return d->m_settings->get("name").toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString BaseInstance::windowTitle() const
|
QString BaseInstance::windowTitle() const
|
||||||
|
@ -51,8 +51,7 @@ class BaseInstance : public QObject
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
protected:
|
protected:
|
||||||
/// no-touchy!
|
/// no-touchy!
|
||||||
BaseInstance(BaseInstancePrivate *d, const QString &rootDir, SettingsObject *settings,
|
BaseInstance(const QString &rootDir, SettingsObject *settings, QObject *parent = 0);
|
||||||
QObject *parent = 0);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// virtual destructor to make sure the destruction is COMPLETE
|
/// virtual destructor to make sure the destruction is COMPLETE
|
||||||
@ -69,8 +68,8 @@ public:
|
|||||||
/// be unique.
|
/// be unique.
|
||||||
virtual QString id() const;
|
virtual QString id() const;
|
||||||
|
|
||||||
virtual void setRunning(bool running) const;
|
void setRunning(bool running);
|
||||||
virtual bool isRunning() const;
|
bool isRunning() const;
|
||||||
|
|
||||||
/// get the type of this instance
|
/// get the type of this instance
|
||||||
QString instanceType() const;
|
QString instanceType() const;
|
||||||
@ -131,26 +130,6 @@ public:
|
|||||||
/// Traits. Normally inside the version, depends on instance implementation.
|
/// Traits. Normally inside the version, depends on instance implementation.
|
||||||
virtual QSet <QString> traits() = 0;
|
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.
|
* Gets the time that the instance was last launched.
|
||||||
* Stored in milliseconds since epoch.
|
* Stored in milliseconds since epoch.
|
||||||
@ -202,7 +181,7 @@ public:
|
|||||||
VersionBrokenFlag = 0x01,
|
VersionBrokenFlag = 0x01,
|
||||||
UpdateAvailable = 0x02
|
UpdateAvailable = 0x02
|
||||||
};
|
};
|
||||||
Q_DECLARE_FLAGS(InstanceFlags, InstanceFlag)
|
Q_DECLARE_FLAGS(InstanceFlags, InstanceFlag);
|
||||||
InstanceFlags flags() const;
|
InstanceFlags flags() const;
|
||||||
void setFlags(const InstanceFlags &flags);
|
void setFlags(const InstanceFlags &flags);
|
||||||
void setFlag(const InstanceFlag flag);
|
void setFlag(const InstanceFlag flag);
|
||||||
@ -232,7 +211,11 @@ protected slots:
|
|||||||
void iconUpdated(QString key);
|
void iconUpdated(QString key);
|
||||||
|
|
||||||
protected:
|
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>)
|
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");
|
m_settings->set("InstanceType", "OneSix");
|
||||||
inst.reset(new OneSixInstance(instDir, m_settings));
|
inst.reset(new OneSixInstance(instDir, m_settings));
|
||||||
inst->setIntendedVersionId(version->descriptor());
|
inst->setIntendedVersionId(version->descriptor());
|
||||||
inst->setShouldUseCustomBaseJar(false);
|
|
||||||
}
|
}
|
||||||
else if (type == FTBInstance)
|
else if (type == FTBInstance)
|
||||||
{
|
{
|
||||||
@ -109,14 +108,12 @@ InstanceFactory::InstCreateError InstanceFactory::createInstance(InstancePtr &in
|
|||||||
m_settings->set("InstanceType", "LegacyFTB");
|
m_settings->set("InstanceType", "LegacyFTB");
|
||||||
inst.reset(new LegacyFTBInstance(instDir, m_settings));
|
inst.reset(new LegacyFTBInstance(instDir, m_settings));
|
||||||
inst->setIntendedVersionId(version->descriptor());
|
inst->setIntendedVersionId(version->descriptor());
|
||||||
inst->setShouldUseCustomBaseJar(false);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_settings->set("InstanceType", "OneSixFTB");
|
m_settings->set("InstanceType", "OneSixFTB");
|
||||||
inst.reset(new OneSixFTBInstance(instDir, m_settings));
|
inst.reset(new OneSixFTBInstance(instDir, m_settings));
|
||||||
inst->setIntendedVersionId(version->descriptor());
|
inst->setIntendedVersionId(version->descriptor());
|
||||||
inst->setShouldUseCustomBaseJar(false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
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 "MultiMC.h"
|
||||||
|
|
||||||
#include "LegacyInstance.h"
|
#include "LegacyInstance.h"
|
||||||
#include "LegacyInstance_p.h"
|
|
||||||
|
|
||||||
#include "logic/MinecraftProcess.h"
|
#include "logic/MinecraftProcess.h"
|
||||||
#include "logic/LegacyUpdate.h"
|
#include "logic/LegacyUpdate.h"
|
||||||
@ -36,15 +35,23 @@
|
|||||||
#include <gui/pages/NotesPage.h>
|
#include <gui/pages/NotesPage.h>
|
||||||
#include <gui/pages/ScreenshotsPage.h>
|
#include <gui/pages/ScreenshotsPage.h>
|
||||||
|
|
||||||
LegacyInstance::LegacyInstance(const QString &rootDir, SettingsObject *settings,
|
LegacyInstance::LegacyInstance(const QString &rootDir, SettingsObject *settings, QObject *parent)
|
||||||
QObject *parent)
|
: BaseInstance(rootDir, settings, parent)
|
||||||
: BaseInstance(new LegacyInstancePrivate(), rootDir, settings, parent)
|
|
||||||
{
|
{
|
||||||
settings->registerSetting("NeedsRebuild", true);
|
settings->registerSetting("NeedsRebuild", true);
|
||||||
settings->registerSetting("ShouldUpdate", false);
|
settings->registerSetting("ShouldUpdate", false);
|
||||||
settings->registerSetting("JarVersion", "Unknown");
|
settings->registerSetting("JarVersion", "Unknown");
|
||||||
settings->registerSetting("LwjglVersion", "2.9.0");
|
settings->registerSetting("LwjglVersion", "2.9.0");
|
||||||
settings->registerSetting("IntendedJarVersion", "");
|
settings->registerSetting("IntendedJarVersion", "");
|
||||||
|
/*
|
||||||
|
* custom base jar has no default. it is determined in code... see the accessor methods for
|
||||||
|
*it
|
||||||
|
*
|
||||||
|
* for instances that DO NOT have the CustomBaseJar setting (legacy instances),
|
||||||
|
* [.]minecraft/bin/mcbackup.jar is the default base jar
|
||||||
|
*/
|
||||||
|
settings->registerSetting("UseCustomBaseJar", true);
|
||||||
|
settings->registerSetting("CustomBaseJar", "");
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<BasePage *> LegacyInstance::getPages()
|
QList<BasePage *> LegacyInstance::getPages()
|
||||||
@ -69,6 +76,46 @@ QString LegacyInstance::dialogTitle()
|
|||||||
return tr("Edit Instance (%1)").arg(name());
|
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()
|
std::shared_ptr<Task> LegacyInstance::doUpdate()
|
||||||
{
|
{
|
||||||
// make sure the jar mods list is initialized by asking for it.
|
// 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()
|
std::shared_ptr<ModList> LegacyInstance::coreModList()
|
||||||
{
|
{
|
||||||
I_D(LegacyInstance);
|
if (!core_mod_list)
|
||||||
if (!d->core_mod_list)
|
|
||||||
{
|
{
|
||||||
d->core_mod_list.reset(new ModList(coreModsDir()));
|
core_mod_list.reset(new ModList(coreModsDir()));
|
||||||
}
|
}
|
||||||
d->core_mod_list->update();
|
core_mod_list->update();
|
||||||
return d->core_mod_list;
|
return core_mod_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<ModList> LegacyInstance::jarModList()
|
std::shared_ptr<ModList> LegacyInstance::jarModList()
|
||||||
{
|
{
|
||||||
I_D(LegacyInstance);
|
if (!jar_mod_list)
|
||||||
if (!d->jar_mod_list)
|
|
||||||
{
|
{
|
||||||
auto list = new ModList(jarModsDir(), modListFile());
|
auto list = new ModList(jarModsDir(), modListFile());
|
||||||
connect(list, SIGNAL(changed()), SLOT(jarModsChanged()));
|
connect(list, SIGNAL(changed()), SLOT(jarModsChanged()));
|
||||||
d->jar_mod_list.reset(list);
|
jar_mod_list.reset(list);
|
||||||
}
|
}
|
||||||
d->jar_mod_list->update();
|
jar_mod_list->update();
|
||||||
return d->jar_mod_list;
|
return jar_mod_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LegacyInstance::jarModsChanged()
|
void LegacyInstance::jarModsChanged()
|
||||||
@ -143,24 +188,22 @@ void LegacyInstance::jarModsChanged()
|
|||||||
|
|
||||||
std::shared_ptr<ModList> LegacyInstance::loaderModList()
|
std::shared_ptr<ModList> LegacyInstance::loaderModList()
|
||||||
{
|
{
|
||||||
I_D(LegacyInstance);
|
if (!loader_mod_list)
|
||||||
if (!d->loader_mod_list)
|
|
||||||
{
|
{
|
||||||
d->loader_mod_list.reset(new ModList(loaderModsDir()));
|
loader_mod_list.reset(new ModList(loaderModsDir()));
|
||||||
}
|
}
|
||||||
d->loader_mod_list->update();
|
loader_mod_list->update();
|
||||||
return d->loader_mod_list;
|
return loader_mod_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<ModList> LegacyInstance::texturePackList()
|
std::shared_ptr<ModList> LegacyInstance::texturePackList()
|
||||||
{
|
{
|
||||||
I_D(LegacyInstance);
|
if (!texture_pack_list)
|
||||||
if (!d->texture_pack_list)
|
|
||||||
{
|
{
|
||||||
d->texture_pack_list.reset(new ModList(texturePacksDir()));
|
texture_pack_list.reset(new ModList(texturePacksDir()));
|
||||||
}
|
}
|
||||||
d->texture_pack_list->update();
|
texture_pack_list->update();
|
||||||
return d->texture_pack_list;
|
return texture_pack_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString LegacyInstance::jarModsDir() const
|
QString LegacyInstance::jarModsDir() const
|
||||||
@ -219,38 +262,32 @@ QString LegacyInstance::instanceConfigFolder() const
|
|||||||
|
|
||||||
bool LegacyInstance::shouldRebuild() const
|
bool LegacyInstance::shouldRebuild() const
|
||||||
{
|
{
|
||||||
I_D(LegacyInstance);
|
return m_settings->get("NeedsRebuild").toBool();
|
||||||
return d->m_settings->get("NeedsRebuild").toBool();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LegacyInstance::setShouldRebuild(bool val)
|
void LegacyInstance::setShouldRebuild(bool val)
|
||||||
{
|
{
|
||||||
I_D(LegacyInstance);
|
m_settings->set("NeedsRebuild", val);
|
||||||
d->m_settings->set("NeedsRebuild", val);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString LegacyInstance::currentVersionId() const
|
QString LegacyInstance::currentVersionId() const
|
||||||
{
|
{
|
||||||
I_D(LegacyInstance);
|
return m_settings->get("JarVersion").toString();
|
||||||
return d->m_settings->get("JarVersion").toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString LegacyInstance::lwjglVersion() const
|
QString LegacyInstance::lwjglVersion() const
|
||||||
{
|
{
|
||||||
I_D(LegacyInstance);
|
return m_settings->get("LwjglVersion").toString();
|
||||||
return d->m_settings->get("LwjglVersion").toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LegacyInstance::setLWJGLVersion(QString val)
|
void LegacyInstance::setLWJGLVersion(QString val)
|
||||||
{
|
{
|
||||||
I_D(LegacyInstance);
|
m_settings->set("LwjglVersion", val);
|
||||||
d->m_settings->set("LwjglVersion", val);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString LegacyInstance::intendedVersionId() const
|
QString LegacyInstance::intendedVersionId() const
|
||||||
{
|
{
|
||||||
I_D(LegacyInstance);
|
return m_settings->get("IntendedJarVersion").toString();
|
||||||
return d->m_settings->get("IntendedJarVersion").toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LegacyInstance::setIntendedVersionId(QString version)
|
bool LegacyInstance::setIntendedVersionId(QString version)
|
||||||
|
@ -56,6 +56,27 @@ public:
|
|||||||
QString resourceDir() const;
|
QString resourceDir() const;
|
||||||
virtual QString instanceConfigFolder() const override;
|
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.
|
* 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
|
* 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 bool prepareForLaunch(AuthSessionPtr account, QString & launchScript) override;
|
||||||
virtual void cleanupAfterRun() override;
|
virtual void cleanupAfterRun() override;
|
||||||
|
|
||||||
virtual QString defaultBaseJar() const override;
|
|
||||||
virtual QString defaultCustomBaseJar() const override;
|
|
||||||
|
|
||||||
virtual QString getStatusbarDescription() 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
|
protected
|
||||||
slots:
|
slots:
|
||||||
virtual void jarModsChanged();
|
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 "logger/QsLog.h"
|
||||||
#include "logic/net/URLConstants.h"
|
#include "logic/net/URLConstants.h"
|
||||||
|
#include "JarUtils.h"
|
||||||
|
|
||||||
|
|
||||||
LegacyUpdate::LegacyUpdate(BaseInstance *inst, QObject *parent) : Task(parent), m_inst(inst)
|
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()
|
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();
|
fmllibsStart();
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LegacyUpdate::fmllibsStart()
|
void LegacyUpdate::fmllibsStart()
|
||||||
@ -415,65 +398,6 @@ void LegacyUpdate::jarFailed()
|
|||||||
emitFailed("Failed to download the minecraft jar. Try again later.");
|
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()
|
void LegacyUpdate::ModTheJar()
|
||||||
{
|
{
|
||||||
LegacyInstance *inst = (LegacyInstance *)m_inst;
|
LegacyInstance *inst = (LegacyInstance *)m_inst;
|
||||||
@ -531,85 +455,13 @@ void LegacyUpdate::ModTheJar()
|
|||||||
// TaskStep(); // STEP 1
|
// TaskStep(); // STEP 1
|
||||||
setStatus(tr("Installing mods: Opening minecraft.jar ..."));
|
setStatus(tr("Installing mods: Opening minecraft.jar ..."));
|
||||||
|
|
||||||
QuaZip zipOut(runnableJar.filePath());
|
const auto & mods = modList->allMods();
|
||||||
if (!zipOut.open(QuaZip::mdCreate))
|
QString outputJarPath = runnableJar.filePath();
|
||||||
|
QString inputJarPath = baseJar.filePath();
|
||||||
|
|
||||||
|
if(!JarUtils::createModdedJar(inputJarPath, outputJarPath, mods))
|
||||||
{
|
{
|
||||||
QFile::remove(runnableJar.filePath());
|
emitFailed(tr("Failed to create the custom Minecraft jar file."));
|
||||||
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!");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
inst->setShouldRebuild(false);
|
inst->setShouldRebuild(false);
|
||||||
|
@ -53,15 +53,6 @@ slots:
|
|||||||
|
|
||||||
void ModTheJar();
|
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:
|
private:
|
||||||
|
|
||||||
std::shared_ptr<QNetworkReply> m_reply;
|
std::shared_ptr<QNetworkReply> m_reply;
|
||||||
|
@ -126,6 +126,11 @@ public:
|
|||||||
return m_dir;
|
return m_dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const QList<Mod> & allMods()
|
||||||
|
{
|
||||||
|
return mods;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void internalSort(QList<Mod> & what);
|
void internalSort(QList<Mod> & what);
|
||||||
struct OrderItem
|
struct OrderItem
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
#include "tasks/SequentialTask.h"
|
#include "tasks/SequentialTask.h"
|
||||||
#include "forge/ForgeInstaller.h"
|
#include "forge/ForgeInstaller.h"
|
||||||
#include "forge/ForgeVersionList.h"
|
#include "forge/ForgeVersionList.h"
|
||||||
#include "OneSixInstance_p.h"
|
|
||||||
#include "MultiMC.h"
|
#include "MultiMC.h"
|
||||||
#include "pathutils.h"
|
#include "pathutils.h"
|
||||||
|
|
||||||
|
@ -21,7 +21,6 @@
|
|||||||
|
|
||||||
#include "logic/OneSixInstance.h"
|
#include "logic/OneSixInstance.h"
|
||||||
|
|
||||||
#include "logic/OneSixInstance_p.h"
|
|
||||||
#include "logic/OneSixUpdate.h"
|
#include "logic/OneSixUpdate.h"
|
||||||
#include "logic/minecraft/InstanceVersion.h"
|
#include "logic/minecraft/InstanceVersion.h"
|
||||||
#include "minecraft/VersionBuildError.h"
|
#include "minecraft/VersionBuildError.h"
|
||||||
@ -39,13 +38,11 @@
|
|||||||
#include "gui/pages/ScreenshotsPage.h"
|
#include "gui/pages/ScreenshotsPage.h"
|
||||||
#include "gui/pages/OtherLogsPage.h"
|
#include "gui/pages/OtherLogsPage.h"
|
||||||
|
|
||||||
OneSixInstance::OneSixInstance(const QString &rootDir, SettingsObject *settings,
|
OneSixInstance::OneSixInstance(const QString &rootDir, SettingsObject *settings, QObject *parent)
|
||||||
QObject *parent)
|
: BaseInstance(rootDir, settings, parent)
|
||||||
: BaseInstance(new OneSixInstancePrivate(), rootDir, settings, parent)
|
|
||||||
{
|
{
|
||||||
I_D(OneSixInstance);
|
m_settings->registerSetting("IntendedVersion", "");
|
||||||
d->m_settings->registerSetting("IntendedVersion", "");
|
version.reset(new InstanceVersion(this, this));
|
||||||
d->version.reset(new InstanceVersion(this, this));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OneSixInstance::init()
|
void OneSixInstance::init()
|
||||||
@ -184,8 +181,6 @@ QDir OneSixInstance::reconstructAssets(std::shared_ptr<InstanceVersion> version)
|
|||||||
|
|
||||||
QStringList OneSixInstance::processMinecraftArgs(AuthSessionPtr session)
|
QStringList OneSixInstance::processMinecraftArgs(AuthSessionPtr session)
|
||||||
{
|
{
|
||||||
I_D(OneSixInstance);
|
|
||||||
auto version = d->version;
|
|
||||||
QString args_pattern = version->minecraftArguments;
|
QString args_pattern = version->minecraftArguments;
|
||||||
for (auto tweaker : version->tweakers)
|
for (auto tweaker : version->tweakers)
|
||||||
{
|
{
|
||||||
@ -207,7 +202,7 @@ QStringList OneSixInstance::processMinecraftArgs(AuthSessionPtr session)
|
|||||||
QString absRootDir = QDir(minecraftRoot()).absolutePath();
|
QString absRootDir = QDir(minecraftRoot()).absolutePath();
|
||||||
token_mapping["game_directory"] = absRootDir;
|
token_mapping["game_directory"] = absRootDir;
|
||||||
QString absAssetsDir = QDir("assets/").absolutePath();
|
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_properties"] = session->serializeUserProperties();
|
||||||
token_mapping["user_type"] = session->user_type;
|
token_mapping["user_type"] = session->user_type;
|
||||||
@ -225,13 +220,11 @@ QStringList OneSixInstance::processMinecraftArgs(AuthSessionPtr session)
|
|||||||
|
|
||||||
bool OneSixInstance::prepareForLaunch(AuthSessionPtr session, QString &launchScript)
|
bool OneSixInstance::prepareForLaunch(AuthSessionPtr session, QString &launchScript)
|
||||||
{
|
{
|
||||||
I_D(OneSixInstance);
|
|
||||||
|
|
||||||
QIcon icon = MMC->icons()->getIcon(iconKey());
|
QIcon icon = MMC->icons()->getIcon(iconKey());
|
||||||
auto pixmap = icon.pixmap(128, 128);
|
auto pixmap = icon.pixmap(128, 128);
|
||||||
pixmap.save(PathCombine(minecraftRoot(), "icon.png"), "PNG");
|
pixmap.save(PathCombine(minecraftRoot(), "icon.png"), "PNG");
|
||||||
|
|
||||||
auto version = d->version;
|
|
||||||
if (!version)
|
if (!version)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
@ -242,20 +235,15 @@ bool OneSixInstance::prepareForLaunch(AuthSessionPtr session, QString &launchScr
|
|||||||
{
|
{
|
||||||
launchScript += "cp " + librariesPath().absoluteFilePath(lib->storagePath()) + "\n";
|
launchScript += "cp " + librariesPath().absoluteFilePath(lib->storagePath()) + "\n";
|
||||||
}
|
}
|
||||||
QString minecraftjarpath;
|
|
||||||
if (version->hasJarMods())
|
if (version->hasJarMods())
|
||||||
{
|
{
|
||||||
for (auto jarmod : version->jarMods)
|
launchScript += "cp " + QDir(instanceRoot()).absoluteFilePath("temp.jar") + "\n";
|
||||||
{
|
|
||||||
launchScript += "cp " + jarmodsPath().absoluteFilePath(jarmod->name) + "\n";
|
|
||||||
}
|
|
||||||
minecraftjarpath = version->id + "/" + version->id + "-stripped.jar";
|
|
||||||
}
|
}
|
||||||
else
|
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())
|
if (!version->mainClass.isEmpty())
|
||||||
{
|
{
|
||||||
@ -320,46 +308,42 @@ void OneSixInstance::cleanupAfterRun()
|
|||||||
|
|
||||||
std::shared_ptr<ModList> OneSixInstance::loaderModList()
|
std::shared_ptr<ModList> OneSixInstance::loaderModList()
|
||||||
{
|
{
|
||||||
I_D(OneSixInstance);
|
if (!loader_mod_list)
|
||||||
if (!d->loader_mod_list)
|
|
||||||
{
|
{
|
||||||
d->loader_mod_list.reset(new ModList(loaderModsDir()));
|
loader_mod_list.reset(new ModList(loaderModsDir()));
|
||||||
}
|
}
|
||||||
d->loader_mod_list->update();
|
loader_mod_list->update();
|
||||||
return d->loader_mod_list;
|
return loader_mod_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<ModList> OneSixInstance::coreModList()
|
std::shared_ptr<ModList> OneSixInstance::coreModList()
|
||||||
{
|
{
|
||||||
I_D(OneSixInstance);
|
if (!core_mod_list)
|
||||||
if (!d->core_mod_list)
|
|
||||||
{
|
{
|
||||||
d->core_mod_list.reset(new ModList(coreModsDir()));
|
core_mod_list.reset(new ModList(coreModsDir()));
|
||||||
}
|
}
|
||||||
d->core_mod_list->update();
|
core_mod_list->update();
|
||||||
return d->core_mod_list;
|
return core_mod_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<ModList> OneSixInstance::resourcePackList()
|
std::shared_ptr<ModList> OneSixInstance::resourcePackList()
|
||||||
{
|
{
|
||||||
I_D(OneSixInstance);
|
if (!resource_pack_list)
|
||||||
if (!d->resource_pack_list)
|
|
||||||
{
|
{
|
||||||
d->resource_pack_list.reset(new ModList(resourcePacksDir()));
|
resource_pack_list.reset(new ModList(resourcePacksDir()));
|
||||||
}
|
}
|
||||||
d->resource_pack_list->update();
|
resource_pack_list->update();
|
||||||
return d->resource_pack_list;
|
return resource_pack_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<ModList> OneSixInstance::texturePackList()
|
std::shared_ptr<ModList> OneSixInstance::texturePackList()
|
||||||
{
|
{
|
||||||
I_D(OneSixInstance);
|
if (!texture_pack_list)
|
||||||
if (!d->texture_pack_list)
|
|
||||||
{
|
{
|
||||||
d->texture_pack_list.reset(new ModList(texturePacksDir()));
|
texture_pack_list.reset(new ModList(texturePacksDir()));
|
||||||
}
|
}
|
||||||
d->texture_pack_list->update();
|
texture_pack_list->update();
|
||||||
return d->texture_pack_list;
|
return texture_pack_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OneSixInstance::setIntendedVersionId(QString version)
|
bool OneSixInstance::setIntendedVersionId(QString version)
|
||||||
@ -386,22 +370,18 @@ bool OneSixInstance::shouldUpdate() const
|
|||||||
|
|
||||||
bool OneSixInstance::versionIsCustom()
|
bool OneSixInstance::versionIsCustom()
|
||||||
{
|
{
|
||||||
I_D(const OneSixInstance);
|
if (version)
|
||||||
auto ver = d->version;
|
|
||||||
if (ver)
|
|
||||||
{
|
{
|
||||||
return !ver->isVanilla();
|
return !version->isVanilla();
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OneSixInstance::versionIsFTBPack()
|
bool OneSixInstance::versionIsFTBPack()
|
||||||
{
|
{
|
||||||
I_D(const OneSixInstance);
|
if (version)
|
||||||
auto ver = d->version;
|
|
||||||
if (ver)
|
|
||||||
{
|
{
|
||||||
return ver->hasFtbPack();
|
return version->hasFtbPack();
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -413,11 +393,10 @@ QString OneSixInstance::currentVersionId() const
|
|||||||
|
|
||||||
void OneSixInstance::reloadVersion()
|
void OneSixInstance::reloadVersion()
|
||||||
{
|
{
|
||||||
I_D(OneSixInstance);
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
d->version->reload(externalPatches());
|
version->reload(externalPatches());
|
||||||
unsetFlag(VersionBrokenFlag);
|
unsetFlag(VersionBrokenFlag);
|
||||||
emit versionReloaded();
|
emit versionReloaded();
|
||||||
}
|
}
|
||||||
@ -426,7 +405,7 @@ void OneSixInstance::reloadVersion()
|
|||||||
}
|
}
|
||||||
catch (MMCError &error)
|
catch (MMCError &error)
|
||||||
{
|
{
|
||||||
d->version->clear();
|
version->clear();
|
||||||
setFlag(VersionBrokenFlag);
|
setFlag(VersionBrokenFlag);
|
||||||
// TODO: rethrow to show some error message(s)?
|
// TODO: rethrow to show some error message(s)?
|
||||||
emit versionReloaded();
|
emit versionReloaded();
|
||||||
@ -436,25 +415,13 @@ void OneSixInstance::reloadVersion()
|
|||||||
|
|
||||||
void OneSixInstance::clearVersion()
|
void OneSixInstance::clearVersion()
|
||||||
{
|
{
|
||||||
I_D(OneSixInstance);
|
version->clear();
|
||||||
d->version->clear();
|
|
||||||
emit versionReloaded();
|
emit versionReloaded();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<InstanceVersion> OneSixInstance::getFullVersion() const
|
std::shared_ptr<InstanceVersion> OneSixInstance::getFullVersion() const
|
||||||
{
|
{
|
||||||
I_D(const OneSixInstance);
|
return version;
|
||||||
return d->version;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString OneSixInstance::defaultBaseJar() const
|
|
||||||
{
|
|
||||||
return "versions/" + intendedVersionId() + "/" + intendedVersionId() + ".jar";
|
|
||||||
}
|
|
||||||
|
|
||||||
QString OneSixInstance::defaultCustomBaseJar() const
|
|
||||||
{
|
|
||||||
return PathCombine(instanceRoot(), "custom.jar");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString OneSixInstance::getStatusbarDescription()
|
QString OneSixInstance::getStatusbarDescription()
|
||||||
|
@ -84,9 +84,6 @@ public:
|
|||||||
/// does this instance have an FTB pack patch inside?
|
/// does this instance have an FTB pack patch inside?
|
||||||
bool versionIsFTBPack();
|
bool versionIsFTBPack();
|
||||||
|
|
||||||
virtual QString defaultBaseJar() const override;
|
|
||||||
virtual QString defaultCustomBaseJar() const override;
|
|
||||||
|
|
||||||
virtual QString getStatusbarDescription() override;
|
virtual QString getStatusbarDescription() override;
|
||||||
|
|
||||||
virtual QDir jarmodsPath() const;
|
virtual QDir jarmodsPath() const;
|
||||||
@ -107,6 +104,14 @@ signals:
|
|||||||
private:
|
private:
|
||||||
QStringList processMinecraftArgs(AuthSessionPtr account);
|
QStringList processMinecraftArgs(AuthSessionPtr account);
|
||||||
QDir reconstructAssets(std::shared_ptr<InstanceVersion> version);
|
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>)
|
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/forge/ForgeMirrors.h"
|
||||||
#include "logic/net/URLConstants.h"
|
#include "logic/net/URLConstants.h"
|
||||||
#include "logic/assets/AssetsUtils.h"
|
#include "logic/assets/AssetsUtils.h"
|
||||||
|
#include "JarUtils.h"
|
||||||
|
|
||||||
OneSixUpdate::OneSixUpdate(OneSixInstance *inst, QObject *parent) : Task(parent), m_inst(inst)
|
OneSixUpdate::OneSixUpdate(OneSixInstance *inst, QObject *parent) : Task(parent), m_inst(inst)
|
||||||
{
|
{
|
||||||
@ -287,23 +288,44 @@ void OneSixUpdate::jarlibFinished()
|
|||||||
OneSixInstance *inst = (OneSixInstance *)m_inst;
|
OneSixInstance *inst = (OneSixInstance *)m_inst;
|
||||||
std::shared_ptr<InstanceVersion> version = inst->getFullVersion();
|
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
|
// create stripped jar, if needed
|
||||||
if (version->hasJarMods())
|
if (version->hasJarMods())
|
||||||
{
|
{
|
||||||
// FIXME: good candidate for moving elsewhere (jar location resolving/version caching).
|
auto sourceJarPath = m_inst->versionsPath().absoluteFilePath(version->id + "/" + version->id + ".jar");
|
||||||
QString version_id = version->id;
|
|
||||||
QString localPath = 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 metacache = MMC->metacache();
|
||||||
auto entry = metacache->resolveEntry("versions", localPath);
|
auto entry = metacache->resolveEntry("versions", localPath);
|
||||||
auto entryStripped = metacache->resolveEntry("versions", strippedPath);
|
|
||||||
|
|
||||||
QString fullJarPath = entry->getFullPath();
|
QString fullJarPath = entry->getFullPath();
|
||||||
QString fullStrippedJarPath = entryStripped->getFullPath();
|
//FIXME: remove need to convert to different objects here
|
||||||
QFileInfo finfo(fullStrippedJarPath);
|
QList<Mod> mods;
|
||||||
if (entry->md5sum != jarHashOnEntry || !finfo.exists())
|
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"))
|
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));
|
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()
|
void OneSixUpdate::fmllibsStart()
|
||||||
{
|
{
|
||||||
// Get the mod list
|
// Get the mod list
|
||||||
|
@ -53,8 +53,6 @@ slots:
|
|||||||
void assetsFinished();
|
void assetsFinished();
|
||||||
void assetsFailed();
|
void assetsFailed();
|
||||||
|
|
||||||
void stripJar(QString origPath, QString newPath);
|
|
||||||
bool MergeZipFiles(QuaZip *into, QString from);
|
|
||||||
private:
|
private:
|
||||||
NetJobPtr jarlibDownloadJob;
|
NetJobPtr jarlibDownloadJob;
|
||||||
NetJobPtr legacyDownloadJob;
|
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())
|
if (!doc.isObject())
|
||||||
{
|
{
|
||||||
|
throw JSONValidationError(filename + " is not an object");
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonObject root = doc.object();
|
QJsonObject root = doc.object();
|
||||||
|
Loading…
Reference in New Issue
Block a user