diff options
| author | Petr Mrázek <peterix@gmail.com> | 2016-06-16 02:20:23 +0200 |
|---|---|---|
| committer | Petr Mrázek <peterix@gmail.com> | 2016-08-01 21:15:08 +0200 |
| commit | 1f2bed2ef119094bdc156aa3a206b93dea5081d1 (patch) | |
| tree | f154e39d3de3a3d71ed868cf396c4361b04e75c5 /api | |
| parent | 57c84ec2b15d8aa6985681f79641f5989c2f049f (diff) | |
| download | PrismLauncher-1f2bed2ef119094bdc156aa3a206b93dea5081d1.tar.gz PrismLauncher-1f2bed2ef119094bdc156aa3a206b93dea5081d1.tar.bz2 PrismLauncher-1f2bed2ef119094bdc156aa3a206b93dea5081d1.zip | |
NOISSUE implement direct java launch
Just running the Java process and giving it params on the command line
Diffstat (limited to 'api')
24 files changed, 975 insertions, 234 deletions
diff --git a/api/logic/BaseInstance.h b/api/logic/BaseInstance.h index 5e587c48..f0fb6096 100644 --- a/api/logic/BaseInstance.h +++ b/api/logic/BaseInstance.h @@ -210,6 +210,11 @@ public: virtual bool reload(); + /** + * 'print' a verbose desription of the instance into a QStringList + */ + virtual QStringList verboseDescription(AuthSessionPtr session) = 0; + signals: /*! * \brief Signal emitted when properties relevant to the instance view change diff --git a/api/logic/CMakeLists.txt b/api/logic/CMakeLists.txt index 1048e091..87908363 100644 --- a/api/logic/CMakeLists.txt +++ b/api/logic/CMakeLists.txt @@ -202,8 +202,14 @@ set(MINECRAFT_SOURCES minecraft/onesix/OneSixVersionFormat.h minecraft/launch/ModMinecraftJar.cpp minecraft/launch/ModMinecraftJar.h - minecraft/launch/LaunchMinecraft.cpp - minecraft/launch/LaunchMinecraft.h + minecraft/launch/DirectJavaLaunch.cpp + minecraft/launch/DirectJavaLaunch.h + minecraft/launch/ExtractNatives.cpp + minecraft/launch/ExtractNatives.h + minecraft/launch/LauncherPartLaunch.cpp + minecraft/launch/LauncherPartLaunch.h + minecraft/launch/PrintInstanceInfo.cpp + minecraft/launch/PrintInstanceInfo.h minecraft/legacy/LegacyModList.h minecraft/legacy/LegacyModList.cpp minecraft/legacy/LegacyUpdate.h diff --git a/api/logic/NullInstance.h b/api/logic/NullInstance.h index fbb2d985..d87fb6f7 100644 --- a/api/logic/NullInstance.h +++ b/api/logic/NullInstance.h @@ -87,4 +87,10 @@ public: { return false; } + QStringList verboseDescription(AuthSessionPtr session) override + { + QStringList out; + out << "Null instance - placeholder."; + return out; + } }; diff --git a/api/logic/java/JavaVersion.cpp b/api/logic/java/JavaVersion.cpp index 84fc48a4..8c1bb430 100644 --- a/api/logic/java/JavaVersion.cpp +++ b/api/logic/java/JavaVersion.cpp @@ -6,7 +6,7 @@ JavaVersion & JavaVersion::operator=(const QString & javaVersionString) { - string = javaVersionString; + m_string = javaVersionString; auto getCapturedInteger = [](const QRegularExpressionMatch & match, const QString &what) -> int { @@ -28,12 +28,12 @@ JavaVersion & JavaVersion::operator=(const QString & javaVersionString) pattern = QRegularExpression("(?<major>[0-9]+)([.](?<minor>[0-9]+))?([.](?<security>[0-9]+))?(-(?<prerelease>[a-zA-Z0-9]+))?"); } - auto match = pattern.match(string); - parseable = match.hasMatch(); - major = getCapturedInteger(match, "major"); - minor = getCapturedInteger(match, "minor"); - security = getCapturedInteger(match, "security"); - prerelease = match.captured("prerelease"); + auto match = pattern.match(m_string); + m_parseable = match.hasMatch(); + m_major = getCapturedInteger(match, "major"); + m_minor = getCapturedInteger(match, "minor"); + m_security = getCapturedInteger(match, "security"); + m_prerelease = match.captured("prerelease"); return *this; } @@ -44,38 +44,38 @@ JavaVersion::JavaVersion(const QString &rhs) QString JavaVersion::toString() { - return string; + return m_string; } bool JavaVersion::requiresPermGen() { - if(parseable) + if(m_parseable) { - return major < 8; + return m_major < 8; } return true; } bool JavaVersion::operator<(const JavaVersion &rhs) { - if(parseable && rhs.parseable) + if(m_parseable && rhs.m_parseable) { - if(major < rhs.major) + if(m_major < rhs.m_major) return true; - if(major > rhs.major) + if(m_major > rhs.m_major) return false; - if(minor < rhs.minor) + if(m_minor < rhs.m_minor) return true; - if(minor > rhs.minor) + if(m_minor > rhs.m_minor) return false; - if(security < rhs.security) + if(m_security < rhs.m_security) return true; - if(security > rhs.security) + if(m_security > rhs.m_security) return false; // everything else being equal, consider prerelease status - bool thisPre = !prerelease.isEmpty(); - bool rhsPre = !rhs.prerelease.isEmpty(); + bool thisPre = !m_prerelease.isEmpty(); + bool rhsPre = !rhs.m_prerelease.isEmpty(); if(thisPre && !rhsPre) { // this is a prerelease and the other one isn't -> lesser @@ -89,21 +89,21 @@ bool JavaVersion::operator<(const JavaVersion &rhs) else if(thisPre && rhsPre) { // both are prereleases - use natural compare... - return Strings::naturalCompare(prerelease, rhs.prerelease, Qt::CaseSensitive) < 0; + return Strings::naturalCompare(m_prerelease, rhs.m_prerelease, Qt::CaseSensitive) < 0; } // neither is prerelease, so they are the same -> this cannot be less than rhs return false; } - else return Strings::naturalCompare(string, rhs.string, Qt::CaseSensitive) < 0; + else return Strings::naturalCompare(m_string, rhs.m_string, Qt::CaseSensitive) < 0; } bool JavaVersion::operator==(const JavaVersion &rhs) { - if(parseable && rhs.parseable) + if(m_parseable && rhs.m_parseable) { - return major == rhs.major && minor == rhs.minor && security == rhs.security && prerelease == rhs.prerelease; + return m_major == rhs.m_major && m_minor == rhs.m_minor && m_security == rhs.m_security && m_prerelease == rhs.m_prerelease; } - return string == rhs.string; + return m_string == rhs.m_string; } bool JavaVersion::operator>(const JavaVersion &rhs) diff --git a/api/logic/java/JavaVersion.h b/api/logic/java/JavaVersion.h index f9a733d3..deba5654 100644 --- a/api/logic/java/JavaVersion.h +++ b/api/logic/java/JavaVersion.h @@ -20,11 +20,23 @@ public: QString toString(); + int major() + { + return m_major; + } + int minor() + { + return m_minor; + } + int security() + { + return m_security; + } private: - QString string; - int major = 0; - int minor = 0; - int security = 0; - bool parseable = false; - QString prerelease; + QString m_string; + int m_major = 0; + int m_minor = 0; + int m_security = 0; + bool m_parseable = false; + QString m_prerelease; }; diff --git a/api/logic/java/JavaVersion_test.cpp b/api/logic/java/JavaVersion_test.cpp index 9dae0ba6..e719ffc8 100644 --- a/api/logic/java/JavaVersion_test.cpp +++ b/api/logic/java/JavaVersion_test.cpp @@ -34,12 +34,12 @@ slots: QFETCH(QString, prerelease); JavaVersion test(string); - QCOMPARE(test.string, string); + QCOMPARE(test.m_string, string); QCOMPARE(test.toString(), string); - QCOMPARE(test.major, major); - QCOMPARE(test.minor, minor); - QCOMPARE(test.security, security); - QCOMPARE(test.prerelease, prerelease); + QCOMPARE(test.m_major, major); + QCOMPARE(test.m_minor, minor); + QCOMPARE(test.m_security, security); + QCOMPARE(test.m_prerelease, prerelease); } void test_Sort_data() diff --git a/api/logic/java/launch/CheckJava.cpp b/api/logic/java/launch/CheckJava.cpp index a4eaa307..41bb6398 100644 --- a/api/logic/java/launch/CheckJava.cpp +++ b/api/logic/java/launch/CheckJava.cpp @@ -53,20 +53,25 @@ void CheckJava::executeTask() QFileInfo javaInfo(realJavaPath); qlonglong javaUnixTime = javaInfo.lastModified().toMSecsSinceEpoch(); auto storedUnixTime = settings->get("JavaTimestamp").toLongLong(); + auto storedArchitecture = settings->get("JavaArchitecture").toString(); + auto storedVersion = settings->get("JavaVersion").toString(); m_javaUnixTime = javaUnixTime; - // if they are not the same, check! - if (javaUnixTime != storedUnixTime) + // if timestamps are not the same, or something is missing, check! + if (javaUnixTime != storedUnixTime || storedVersion.size() == 0 || storedArchitecture.size() == 0) { m_JavaChecker = std::make_shared<JavaChecker>(); - QString errorLog; - QString version; emit logLine(tr("Checking Java version..."), MessageLevel::MultiMC); - connect(m_JavaChecker.get(), &JavaChecker::checkFinished, this, - &CheckJava::checkJavaFinished); + connect(m_JavaChecker.get(), &JavaChecker::checkFinished, this, &CheckJava::checkJavaFinished); m_JavaChecker->m_path = realJavaPath; m_JavaChecker->performCheck(); return; } + else + { + auto verString = instance->settings()->get("JavaVersion").toString(); + auto archString = instance->settings()->get("JavaArchitecture").toString(); + printJavaInfo(verString, archString); + } emitSucceeded(); } @@ -83,10 +88,15 @@ void CheckJava::checkJavaFinished(JavaCheckResult result) else { auto instance = m_parent->instance(); - emit logLine(tr("Java version is %1!\n").arg(result.javaVersion.toString()), - MessageLevel::MultiMC); + printJavaInfo(result.javaVersion.toString(), result.mojangPlatform); instance->settings()->set("JavaVersion", result.javaVersion.toString()); + instance->settings()->set("JavaArchitecture", result.mojangPlatform); instance->settings()->set("JavaTimestamp", m_javaUnixTime); emitSucceeded(); } } + +void CheckJava::printJavaInfo(const QString& version, const QString& architecture) +{ + emit logLine(tr("Java is version %1, using %2-bit architecture.\n\n").arg(version, architecture), MessageLevel::MultiMC); +} diff --git a/api/logic/java/launch/CheckJava.h b/api/logic/java/launch/CheckJava.h index b63dd4f4..118da225 100644 --- a/api/logic/java/launch/CheckJava.h +++ b/api/logic/java/launch/CheckJava.h @@ -35,6 +35,9 @@ private slots: void checkJavaFinished(JavaCheckResult result); private: + void printJavaInfo(const QString & version, const QString & architecture); + +private: QString m_javaPath; qlonglong m_javaUnixTime; JavaCheckerPtr m_JavaChecker; diff --git a/api/logic/minecraft/MinecraftInstance.cpp b/api/logic/minecraft/MinecraftInstance.cpp index 405ccd26..8cc4f805 100644 --- a/api/logic/minecraft/MinecraftInstance.cpp +++ b/api/logic/minecraft/MinecraftInstance.cpp @@ -1,4 +1,6 @@ #include "MinecraftInstance.h" +#include <minecraft/launch/ExtractNatives.h> +#include <minecraft/launch/PrintInstanceInfo.h> #include <settings/Setting.h> #include "settings/SettingsObject.h" #include "Env.h" @@ -9,6 +11,15 @@ #include <FileSystem.h> #include <java/JavaVersion.h> +#include "launch/LaunchTask.h" +#include "launch/steps/PostLaunchCommand.h" +#include "launch/steps/Update.h" +#include "launch/steps/PreLaunchCommand.h" +#include "launch/steps/TextPrint.h" +#include "minecraft/launch/LauncherPartLaunch.h" +#include "minecraft/launch/ModMinecraftJar.h" +#include "java/launch/CheckJava.h" + #define IBUS "@im=ibus" // all of this because keeping things compatible with deprecated old settings @@ -52,6 +63,7 @@ MinecraftInstance::MinecraftInstance(SettingsObjectPtr globalSettings, SettingsO // special! m_settings->registerPassthrough(globalSettings->getSetting("JavaTimestamp"), javaOrLocation); m_settings->registerPassthrough(globalSettings->getSetting("JavaVersion"), javaOrLocation); + m_settings->registerPassthrough(globalSettings->getSetting("JavaArchitecture"), javaOrLocation); // Window Size auto windowSetting = m_settings->registerSetting("OverrideWindow", false); @@ -64,6 +76,10 @@ MinecraftInstance::MinecraftInstance(SettingsObjectPtr globalSettings, SettingsO m_settings->registerOverride(globalSettings->getSetting("MinMemAlloc"), memorySetting); m_settings->registerOverride(globalSettings->getSetting("MaxMemAlloc"), memorySetting); m_settings->registerOverride(globalSettings->getSetting("PermGen"), memorySetting); + + // Minecraft launch method + auto launchMethodOverride = m_settings->registerSetting("OverrideMCLaunchMethod", false); + m_settings->registerOverride(globalSettings->getSetting("MCLaunchMethod"), launchMethodOverride); } QString MinecraftInstance::minecraftRoot() const @@ -105,7 +121,7 @@ QStringList MinecraftInstance::javaArguments() const args << QString("-Xmx%1m").arg(settings()->get("MaxMemAlloc").toInt()); // No PermGen in newer java. - JavaVersion javaVersion(settings()->get("JavaVersion").toString()); + JavaVersion javaVersion = getJavaVersion(); if(javaVersion.requiresPermGen()) { auto permgen = settings()->get("PermGen").toInt(); @@ -116,7 +132,6 @@ QStringList MinecraftInstance::javaArguments() const } args << "-Duser.language=en"; - args << "-jar" << FS::PathCombine(QCoreApplication::applicationDirPath(), "jars", "NewLaunch.jar"); return args; } @@ -366,4 +381,95 @@ QString MinecraftInstance::getStatusbarDescription() return description; } +std::shared_ptr<LaunchTask> MinecraftInstance::createLaunchTask(AuthSessionPtr session) +{ + auto process = LaunchTask::create(std::dynamic_pointer_cast<MinecraftInstance>(getSharedPtr())); + auto pptr = process.get(); + + // print a header + { + process->appendStep(std::make_shared<TextPrint>(pptr, "Minecraft folder is:\n" + minecraftRoot() + "\n\n", MessageLevel::MultiMC)); + } + + // check java + { + auto step = std::make_shared<CheckJava>(pptr); + process->appendStep(step); + } + + // check launch method + QStringList validMethods = validLaunchMethods(); + QString method = launchMethod(); + if(!validMethods.contains(method)) + { + process->appendStep(std::make_shared<TextPrint>(pptr, "Selected launch method \"" + method + "\" is not valid.\n", MessageLevel::Fatal)); + return process; + } + + // run pre-launch command if that's needed + if(getPreLaunchCommand().size()) + { + auto step = std::make_shared<PreLaunchCommand>(pptr); + step->setWorkingDirectory(minecraftRoot()); + process->appendStep(step); + } + + // if we aren't in offline mode,. + if(session->status != AuthSession::PlayableOffline) + { + process->appendStep(std::make_shared<Update>(pptr)); + } + + // if there are any jar mods + if(getJarMods().size()) + { + auto step = std::make_shared<ModMinecraftJar>(pptr); + process->appendStep(step); + } + + // print some instance info here... + { + auto step = std::make_shared<PrintInstanceInfo>(pptr, session); + process->appendStep(step); + } + + // extract native jars if needed + auto jars = getNativeJars(); + if(jars.size()) + { + auto step = std::make_shared<ExtractNatives>(pptr); + process->appendStep(step); + } + + { + // actually launch the game + auto step = createMainLaunchStep(pptr, session); + process->appendStep(step); + } + + // run post-exit command if that's needed + if(getPostExitCommand().size()) + { + auto step = std::make_shared<PostLaunchCommand>(pptr); + step->setWorkingDirectory(minecraftRoot()); + process->appendStep(step); + } + if (session) + { + process->setCensorFilter(createCensorFilterFromSession(session)); + } + return process; +} + +QString MinecraftInstance::launchMethod() +{ + return m_settings->get("MCLaunchMethod").toString(); +} + +JavaVersion MinecraftInstance::getJavaVersion() const +{ + return JavaVersion(settings()->get("JavaVersion").toString()); +} + + #include "MinecraftInstance.moc" diff --git a/api/logic/minecraft/MinecraftInstance.h b/api/logic/minecraft/MinecraftInstance.h index cd3a8d90..3aef2969 100644 --- a/api/logic/minecraft/MinecraftInstance.h +++ b/api/logic/minecraft/MinecraftInstance.h @@ -1,5 +1,6 @@ #pragma once #include "BaseInstance.h" +#include <java/JavaVersion.h> #include "minecraft/Mod.h" #include <QProcess> @@ -7,6 +8,7 @@ class ModList; class WorldList; +class LaunchStep; class MULTIMC_LOGIC_EXPORT MinecraftInstance: public BaseInstance { @@ -36,7 +38,7 @@ public: return QList<Mod>(); } - /// get the launch script to be used with this + virtual std::shared_ptr<LaunchTask> createLaunchTask(AuthSessionPtr account) override; virtual QString createLaunchScript(AuthSessionPtr session) = 0; //FIXME: nuke? @@ -60,8 +62,22 @@ public: virtual QString getStatusbarDescription() override; + virtual QStringList getClassPath() const = 0; + virtual QStringList getNativeJars() const = 0; + + virtual QString getMainClass() const = 0; + + virtual QString getNativePath() const = 0; + + virtual QStringList processMinecraftArgs(AuthSessionPtr account) const = 0; + + virtual JavaVersion getJavaVersion() const; + protected: QMap<QString, QString> createCensorFilterFromSession(AuthSessionPtr session); + virtual QStringList validLaunchMethods() = 0; + virtual QString launchMethod(); + virtual std::shared_ptr<LaunchStep> createMainLaunchStep(LaunchTask *parent, AuthSessionPtr session) = 0; private: QString prettifyTimeDuration(int64_t duration); }; diff --git a/api/logic/minecraft/MinecraftProfile.cpp b/api/logic/minecraft/MinecraftProfile.cpp index 70d0cee4..19127a54 100644 --- a/api/logic/minecraft/MinecraftProfile.cpp +++ b/api/logic/minecraft/MinecraftProfile.cpp @@ -573,6 +573,26 @@ const QList<LibraryPtr> & MinecraftProfile::getLibraries() const return m_libraries; } +void MinecraftProfile::getLibraryFiles(const QString& architecture, QStringList& jars, QStringList& nativeJars) const +{ + QStringList native32, native64; + jars.clear(); + nativeJars.clear(); + for (auto lib : getLibraries()) + { + lib->getApplicableFiles(currentSystem, jars, nativeJars, native32, native64); + } + if(architecture == "32") + { + nativeJars.append(native32); + } + else if(architecture == "64") + { + nativeJars.append(native64); + } +} + + QString MinecraftProfile::getMainJarUrl() const { auto iter = mojangDownloads.find("client"); diff --git a/api/logic/minecraft/MinecraftProfile.h b/api/logic/minecraft/MinecraftProfile.h index ca9288ad..cc9b89b1 100644 --- a/api/logic/minecraft/MinecraftProfile.h +++ b/api/logic/minecraft/MinecraftProfile.h @@ -110,6 +110,7 @@ public: /* getters for profile variables */ const QStringList & getTweakers() const; const QList<JarmodPtr> & getJarMods() const; const QList<LibraryPtr> & getLibraries() const; + void getLibraryFiles(const QString & architecture, QStringList & jars, QStringList & nativeJars) const; QString getMainJarUrl() const; bool hasTrait(const QString & trait) const; ProblemSeverity getProblemSeverity() const; diff --git a/api/logic/minecraft/launch/DirectJavaLaunch.cpp b/api/logic/minecraft/launch/DirectJavaLaunch.cpp new file mode 100644 index 00000000..c46cdcd4 --- /dev/null +++ b/api/logic/minecraft/launch/DirectJavaLaunch.cpp @@ -0,0 +1,149 @@ +/* Copyright 2013-2015 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "DirectJavaLaunch.h" +#include <launch/LaunchTask.h> +#include <minecraft/MinecraftInstance.h> +#include <FileSystem.h> +#include <QStandardPaths> + +DirectJavaLaunch::DirectJavaLaunch(LaunchTask *parent) : LaunchStep(parent) +{ + connect(&m_process, &LoggedProcess::log, this, &DirectJavaLaunch::logLines); + connect(&m_process, &LoggedProcess::stateChanged, this, &DirectJavaLaunch::on_state); +} + +void DirectJavaLaunch::executeTask() +{ + auto instance = m_parent->instance(); + std::shared_ptr<MinecraftInstance> minecraftInstance = std::dynamic_pointer_cast<MinecraftInstance>(instance); + QStringList args = minecraftInstance->javaArguments(); + + // HACK: this is a workaround for MCL-3732 - 'server-resource-packs' is created. + if(!FS::ensureFolderPathExists(FS::PathCombine(minecraftInstance->minecraftRoot(), "server-resource-packs"))) + { + emit logLine(tr("Couldn't create the 'server-resource-packs' folder"), MessageLevel::Error); + } + + args.append("-Djava.library.path=" + minecraftInstance->getNativePath()); + + auto classPathEntries = minecraftInstance->getClassPath(); + args.append("-cp"); + QString classpath; +#ifdef Q_OS_WIN32 + classpath = classPathEntries.join(';'); +#else + classpath = classPathEntries.join(':'); +#endif + args.append(classpath); + args.append(minecraftInstance->getMainClass()); + + QString allArgs = args.join(", "); + emit logLine("Java Arguments:\n[" + m_parent->censorPrivateInfo(allArgs) + "]\n\n", MessageLevel::MultiMC); + + auto javaPath = FS::ResolveExecutable(instance->settings()->get("JavaPath").toString()); + + m_process.setProcessEnvironment(instance->createEnvironment()); + + auto mcArgs = minecraftInstance->processMinecraftArgs(m_session); + args.append(mcArgs); + + QString wrapperCommand = instance->getWrapperCommand(); + if(!wrapperCommand.isEmpty()) + { + auto realWrapperCommand = QStandardPaths::findExecutable(wrapperCommand); + if (realWrapperCommand.isEmpty()) + { + QString reason = tr("The wrapper command \"%1\" couldn't be found.").arg(wrapperCommand); + emit logLine(reason, MessageLevel::Fatal); + emitFailed(reason); + return; + } + emit logLine("Wrapper command is:\n" + wrapperCommand + "\n\n", MessageLevel::MultiMC); + args.prepend(javaPath); + m_process.start(wrapperCommand, args); + } + else + { + m_process.start(javaPath, args); + } +} + +void DirectJavaLaunch::on_state(LoggedProcess::State state) +{ + switch(state) + { + case LoggedProcess::FailedToStart: + { + //: Error message displayed if instace can't start + QString reason = tr("Could not launch minecraft!"); + emit logLine(reason, MessageLevel::Fatal); + emitFailed(reason); + return; + } + case LoggedProcess::Aborted: + case LoggedProcess::Crashed: + + { + m_parent->setPid(-1); + emitFailed("Game crashed."); + return; + } + case LoggedProcess::Finished: + { + m_parent->setPid(-1); + // if the exit code wasn't 0, report this as a crash + auto exitCode = m_process.exitCode(); + if(exitCode != 0) + { + emitFailed("Game crashed."); + return; + } + //FIXME: make this work again + // m_postlaunchprocess.processEnvironment().insert("INST_EXITCODE", QString(exitCode)); + // run post-exit + emitSucceeded(); + break; + } + case LoggedProcess::Running: + emit logLine(tr("Minecraft process ID: %1\n\n").arg(m_process.processId()), MessageLevel::MultiMC); + m_parent->setPid(m_process.processId()); + m_parent->instance()->setLastLaunch(); + break; + default: + break; + } +} + +void DirectJavaLaunch::setWorkingDirectory(const QString &wd) +{ + m_process.setWorkingDirectory(wd); +} + +void DirectJavaLaunch::proceed() +{ + // nil +} + +bool DirectJavaLaunch::abort() +{ + auto state = m_process.state(); + if (state == LoggedProcess::Running || state == LoggedProcess::Starting) + { + m_process.kill(); + } + return true; +} + diff --git a/api/logic/minecraft/launch/DirectJavaLaunch.h b/api/logic/minecraft/launch/DirectJavaLaunch.h new file mode 100644 index 00000000..0e3d66cc --- /dev/null +++ b/api/logic/minecraft/launch/DirectJavaLaunch.h @@ -0,0 +1,47 @@ +/* Copyright 2013-2015 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <launch/LaunchStep.h> +#include <launch/LoggedProcess.h> +#include <minecraft/auth/AuthSession.h> + +class DirectJavaLaunch: public LaunchStep +{ + Q_OBJECT +public: + explicit DirectJavaLaunch(LaunchTask *parent); + virtual void executeTask(); + virtual bool abort(); + virtual void proceed(); + virtual bool canAbort() const + { + return true; + } + void setWorkingDirectory(const QString &wd); + void setAuthSession(AuthSessionPtr session) + { + m_session = session; + } +private slots: + void on_state(LoggedProcess::State state); + +private: + LoggedProcess m_process; + QString m_command; + AuthSessionPtr m_session; +}; + diff --git a/api/logic/minecraft/launch/ExtractNatives.cpp b/api/logic/minecraft/launch/ExtractNatives.cpp new file mode 100644 index 00000000..089e2559 --- /dev/null +++ b/api/logic/minecraft/launch/ExtractNatives.cpp @@ -0,0 +1,86 @@ +/* Copyright 2013-2016 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 "ExtractNatives.h" +#include <minecraft/MinecraftInstance.h> +#include <launch/LaunchTask.h> + +#include <quazip.h> +#include <JlCompress.h> +#include <quazipdir.h> +#include "MMCZip.h" +#include "FileSystem.h" +#include <QDir> + +static QString replaceSuffix (QString target, const QString &suffix, const QString &replacement) +{ + if (!target.endsWith(suffix)) + { + return target; + } + target.resize(target.length() - suffix.length()); + return target + replacement; +} + +static bool unzipNatives(QString source, QString targetFolder, bool applyJnilibHack) +{ + QuaZip zip(source); + if(!zip.open(QuaZip::mdUnzip)) + { + return false; + } + QDir directory(targetFolder); + if (!zip.goToFirstFile()) + { + return false; + } + do + { + QString name = zip.getCurrentFileName(); + if(applyJnilibHack) + { + name = replaceSuffix(name, ".jnilib", ".dylib"); + } + QString absFilePath = directory.absoluteFilePath(name); + if (!MMCZip::extractFile(&zip, "", absFilePath)) + { + return false; + } + } while (zip.goToNextFile()); + zip.close(); + if(zip.getZipError()!=0) + { + return false; + } + return true; +} + +void ExtractNatives::executeTask() +{ + auto instance = m_parent->instance(); + std::shared_ptr<MinecraftInstance> minecraftInstance = std::dynamic_pointer_cast<MinecraftInstance>(instance); + auto outputPath = minecraftInstance->getNativePath(); + auto toExtract = minecraftInstance->getNativeJars(); + auto javaVersion = minecraftInstance->getJavaVersion(); + bool jniHackEnabled = javaVersion.major() >= 8; + for(const auto &source: toExtract) + { |
