NOISSUE implement direct java launch
Just running the Java process and giving it params on the command line
This commit is contained in:
parent
57c84ec2b1
commit
1f2bed2ef1
@ -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
|
||||
|
@ -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
|
||||
|
@ -87,4 +87,10 @@ public:
|
||||
{
|
||||
return false;
|
||||
}
|
||||
QStringList verboseDescription(AuthSessionPtr session) override
|
||||
{
|
||||
QStringList out;
|
||||
out << "Null instance - placeholder.";
|
||||
return out;
|
||||
}
|
||||
};
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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()
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -34,6 +34,9 @@ public:
|
||||
private slots:
|
||||
void checkJavaFinished(JavaCheckResult result);
|
||||
|
||||
private:
|
||||
void printJavaInfo(const QString & version, const QString & architecture);
|
||||
|
||||
private:
|
||||
QString m_javaPath;
|
||||
qlonglong m_javaUnixTime;
|
||||
|
@ -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"
|
||||
|
@ -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);
|
||||
};
|
||||
|
@ -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");
|
||||
|
@ -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;
|
||||
|
149
api/logic/minecraft/launch/DirectJavaLaunch.cpp
Normal file
149
api/logic/minecraft/launch/DirectJavaLaunch.cpp
Normal file
@ -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;
|
||||
}
|
||||
|
47
api/logic/minecraft/launch/DirectJavaLaunch.h
Normal file
47
api/logic/minecraft/launch/DirectJavaLaunch.h
Normal file
@ -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;
|
||||
};
|
||||
|
86
api/logic/minecraft/launch/ExtractNatives.cpp
Normal file
86
api/logic/minecraft/launch/ExtractNatives.cpp
Normal file
@ -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)
|
||||
{
|
||||
if(!unzipNatives(source, outputPath, jniHackEnabled))
|
||||
{
|
||||
emitFailed(tr("Couldn't extract native jar '%1' to destination '%2'").arg(source, outputPath));
|
||||
}
|
||||
}
|
||||
emitSucceeded();
|
||||
}
|
37
api/logic/minecraft/launch/ExtractNatives.h
Normal file
37
api/logic/minecraft/launch/ExtractNatives.h
Normal file
@ -0,0 +1,37 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <launch/LaunchStep.h>
|
||||
#include <memory>
|
||||
#include "minecraft/auth/AuthSession.h"
|
||||
|
||||
// FIXME: temporary wrapper for existing task.
|
||||
class ExtractNatives: public LaunchStep
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ExtractNatives(LaunchTask *parent) : LaunchStep(parent){};
|
||||
virtual ~ExtractNatives(){};
|
||||
|
||||
virtual void executeTask();
|
||||
virtual bool canAbort() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -13,25 +13,25 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "LaunchMinecraft.h"
|
||||
#include "LauncherPartLaunch.h"
|
||||
#include <QCoreApplication>
|
||||
#include <launch/LaunchTask.h>
|
||||
#include <minecraft/MinecraftInstance.h>
|
||||
#include <FileSystem.h>
|
||||
#include <QStandardPaths>
|
||||
|
||||
LaunchMinecraft::LaunchMinecraft(LaunchTask *parent) : LaunchStep(parent)
|
||||
LauncherPartLaunch::LauncherPartLaunch(LaunchTask *parent) : LaunchStep(parent)
|
||||
{
|
||||
connect(&m_process, &LoggedProcess::log, this, &LaunchMinecraft::logLines);
|
||||
connect(&m_process, &LoggedProcess::stateChanged, this, &LaunchMinecraft::on_state);
|
||||
connect(&m_process, &LoggedProcess::log, this, &LauncherPartLaunch::logLines);
|
||||
connect(&m_process, &LoggedProcess::stateChanged, this, &LauncherPartLaunch::on_state);
|
||||
}
|
||||
|
||||
void LaunchMinecraft::executeTask()
|
||||
void LauncherPartLaunch::executeTask()
|
||||
{
|
||||
auto instance = m_parent->instance();
|
||||
std::shared_ptr<MinecraftInstance> minecraftInstance = std::dynamic_pointer_cast<MinecraftInstance>(instance);
|
||||
|
||||
m_launchScript = minecraftInstance->createLaunchScript(m_session);
|
||||
|
||||
QStringList args = minecraftInstance->javaArguments();
|
||||
|
||||
// HACK: this is a workaround for MCL-3732 - 'server-resource-packs' is created.
|
||||
@ -47,6 +47,8 @@ void LaunchMinecraft::executeTask()
|
||||
|
||||
m_process.setProcessEnvironment(instance->createEnvironment());
|
||||
|
||||
args << "-jar" << FS::PathCombine(QCoreApplication::applicationDirPath(), "jars", "NewLaunch.jar");
|
||||
|
||||
QString wrapperCommand = instance->getWrapperCommand();
|
||||
if(!wrapperCommand.isEmpty())
|
||||
{
|
||||
@ -68,7 +70,7 @@ void LaunchMinecraft::executeTask()
|
||||
}
|
||||
}
|
||||
|
||||
void LaunchMinecraft::on_state(LoggedProcess::State state)
|
||||
void LauncherPartLaunch::on_state(LoggedProcess::State state)
|
||||
{
|
||||
switch(state)
|
||||
{
|
||||
@ -120,12 +122,12 @@ void LaunchMinecraft::on_state(LoggedProcess::State state)
|
||||
}
|
||||
}
|
||||
|
||||
void LaunchMinecraft::setWorkingDirectory(const QString &wd)
|
||||
void LauncherPartLaunch::setWorkingDirectory(const QString &wd)
|
||||
{
|
||||
m_process.setWorkingDirectory(wd);
|
||||
}
|
||||
|
||||
void LaunchMinecraft::proceed()
|
||||
void LauncherPartLaunch::proceed()
|
||||
{
|
||||
if(mayProceed)
|
||||
{
|
||||
@ -135,7 +137,7 @@ void LaunchMinecraft::proceed()
|
||||
}
|
||||
}
|
||||
|
||||
bool LaunchMinecraft::abort()
|
||||
bool LauncherPartLaunch::abort()
|
||||
{
|
||||
if(mayProceed)
|
||||
{
|
@ -19,11 +19,11 @@
|
||||
#include <launch/LoggedProcess.h>
|
||||
#include <minecraft/auth/AuthSession.h>
|
||||
|
||||
class LaunchMinecraft: public LaunchStep
|
||||
class LauncherPartLaunch: public LaunchStep
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit LaunchMinecraft(LaunchTask *parent);
|
||||
explicit LauncherPartLaunch(LaunchTask *parent);
|
||||
virtual void executeTask();
|
||||
virtual bool abort();
|
||||
virtual void proceed();
|
||||
@ -36,13 +36,14 @@ public:
|
||||
{
|
||||
m_session = session;
|
||||
}
|
||||
|
||||
private slots:
|
||||
void on_state(LoggedProcess::State state);
|
||||
|
||||
private:
|
||||
LoggedProcess m_process;
|
||||
QString m_command;
|
||||
QString m_launchScript;
|
||||
AuthSessionPtr m_session;
|
||||
QString m_launchScript;
|
||||
bool mayProceed = false;
|
||||
};
|
25
api/logic/minecraft/launch/PrintInstanceInfo.cpp
Normal file
25
api/logic/minecraft/launch/PrintInstanceInfo.cpp
Normal file
@ -0,0 +1,25 @@
|
||||
/* 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 "PrintInstanceInfo.h"
|
||||
#include <launch/LaunchTask.h>
|
||||
|
||||
void PrintInstanceInfo::executeTask()
|
||||
{
|
||||
auto instance = m_parent->instance();
|
||||
auto lines = instance->verboseDescription(m_session);
|
||||
logLines(lines, MessageLevel::MultiMC);
|
||||
emitSucceeded();
|
||||
}
|
38
api/logic/minecraft/launch/PrintInstanceInfo.h
Normal file
38
api/logic/minecraft/launch/PrintInstanceInfo.h
Normal file
@ -0,0 +1,38 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <launch/LaunchStep.h>
|
||||
#include <memory>
|
||||
#include "minecraft/auth/AuthSession.h"
|
||||
|
||||
// FIXME: temporary wrapper for existing task.
|
||||
class PrintInstanceInfo: public LaunchStep
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit PrintInstanceInfo(LaunchTask *parent, AuthSessionPtr session) : LaunchStep(parent), m_session(session) {};
|
||||
virtual ~PrintInstanceInfo(){};
|
||||
|
||||
virtual void executeTask();
|
||||
virtual bool canAbort() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
private:
|
||||
AuthSessionPtr m_session;
|
||||
};
|
||||
|
@ -14,6 +14,7 @@
|
||||
*/
|
||||
|
||||
#include <QFileInfo>
|
||||
#include <minecraft/launch/LauncherPartLaunch.h>
|
||||
#include <QDir>
|
||||
#include <settings/Setting.h>
|
||||
|
||||
@ -21,14 +22,6 @@
|
||||
|
||||
#include "minecraft/legacy/LegacyUpdate.h"
|
||||
#include "minecraft/legacy/LegacyModList.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/LaunchMinecraft.h"
|
||||
#include "minecraft/launch/ModMinecraftJar.h"
|
||||
#include "java/launch/CheckJava.h"
|
||||
#include "minecraft/ModList.h"
|
||||
#include "minecraft/WorldList.h"
|
||||
#include <MMCZip.h>
|
||||
@ -102,58 +95,6 @@ std::shared_ptr<Task> LegacyInstance::createUpdateTask()
|
||||
return std::shared_ptr<Task>(new LegacyUpdate(this, this));
|
||||
}
|
||||
|
||||
std::shared_ptr<LaunchTask> LegacyInstance::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));
|
||||
}
|
||||
{
|
||||
auto step = std::make_shared<CheckJava>(pptr);
|
||||
process->appendStep(step);
|
||||
}
|
||||
// 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);
|
||||
}
|
||||
// actually launch the game
|
||||
{
|
||||
auto step = std::make_shared<LaunchMinecraft>(pptr);
|
||||
step->setWorkingDirectory(minecraftRoot());
|
||||
step->setAuthSession(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;
|
||||
}
|
||||
|
||||
std::shared_ptr<Task> LegacyInstance::createJarModdingTask()
|
||||
{
|
||||
class JarModTask : public Task
|
||||
@ -255,11 +196,35 @@ QString LegacyInstance::createLaunchScript(AuthSessionPtr session)
|
||||
launchScript += "sessionId " + session->session + "\n";
|
||||
launchScript += "windowTitle " + windowTitle() + "\n";
|
||||
launchScript += "windowParams " + windowParams + "\n";
|
||||
launchScript += "lwjgl " + lwjgl + "\n";
|
||||
launchScript += "launcher legacy\n";
|
||||
launchScript += "cp bin/minecraft.jar\n";
|
||||
launchScript += "cp " + lwjgl + "/lwjgl.jar\n";
|
||||
launchScript += "cp " + lwjgl + "/lwjgl_util.jar\n";
|
||||
launchScript += "cp " + lwjgl + "/jinput.jar\n";
|
||||
launchScript += "natives " + lwjgl + "/natives\n";
|
||||
launchScript += "traits legacyLaunch\n";
|
||||
launchScript += "launcher onesix\n";
|
||||
return launchScript;
|
||||
}
|
||||
|
||||
std::shared_ptr<LaunchStep> LegacyInstance::createMainLaunchStep(LaunchTask * parent, AuthSessionPtr session)
|
||||
{
|
||||
auto step = std::make_shared<LauncherPartLaunch>(parent);
|
||||
step->setWorkingDirectory(minecraftRoot());
|
||||
step->setAuthSession(session);
|
||||
return step;
|
||||
}
|
||||
|
||||
QString LegacyInstance::launchMethod()
|
||||
{
|
||||
return "Legacy";
|
||||
}
|
||||
|
||||
QStringList LegacyInstance::validLaunchMethods()
|
||||
{
|
||||
return {"Legacy"};
|
||||
}
|
||||
|
||||
|
||||
void LegacyInstance::cleanupAfterRun()
|
||||
{
|
||||
// FIXME: delete the launcher and icons and whatnot.
|
||||
@ -452,3 +417,112 @@ QString LegacyInstance::typeName() const
|
||||
{
|
||||
return tr("Legacy");
|
||||
}
|
||||
|
||||
QStringList LegacyInstance::verboseDescription(AuthSessionPtr session)
|
||||
{
|
||||
QStringList out;
|
||||
|
||||
auto alltraits = traits();
|
||||
if(alltraits.size())
|
||||
{
|
||||
out << "Traits:";
|
||||
for (auto trait : alltraits)
|
||||
{
|
||||
out << " " + trait;
|
||||
}
|
||||
out << "";
|
||||
}
|
||||
|
||||
if(loaderModList()->size())
|
||||
{
|
||||
out << "Mods:";
|
||||
for(auto & mod: loaderModList()->allMods())
|
||||
{
|
||||
if(!mod.enabled())
|
||||
continue;
|
||||
if(mod.type() == Mod::MOD_FOLDER)
|
||||
continue;
|
||||
// TODO: proper implementation would need to descend into folders.
|
||||
|
||||
out << " " + mod.filename().completeBaseName();
|
||||
}
|
||||
out << "";
|
||||
}
|
||||
|
||||
if(coreModList()->size())
|
||||
{
|
||||
out << "Core Mods:";
|
||||
for(auto & coremod: coreModList()->allMods())
|
||||
{
|
||||
if(!coremod.enabled())
|
||||
continue;
|
||||
if(coremod.type() == Mod::MOD_FOLDER)
|
||||
continue;
|
||||
// TODO: proper implementation would need to descend into folders.
|
||||
|
||||
out << " " + coremod.filename().completeBaseName();
|
||||
}
|
||||
out << "";
|
||||
}
|
||||
|
||||
if(jarModList()->size())
|
||||
{
|
||||
out << "Jar Mods:";
|
||||
for(auto & jarmod: jarModList()->allMods())
|
||||
{
|
||||
out << " " + jarmod.name() + " (" + jarmod.filename().filePath() + ")";
|
||||
}
|
||||
out << "";
|
||||
}
|
||||
|
||||
QString windowParams;
|
||||
if (settings()->get("LaunchMaximized").toBool())
|
||||
{
|
||||
out << "Window size: max (if available)";
|
||||
}
|
||||
else
|
||||
{
|
||||
auto width = settings()->get("MinecraftWinWidth").toInt();
|
||||
auto height = settings()->get("MinecraftWinHeight").toInt();
|
||||
out << "Window size: " + QString::number(width) + " x " + QString::number(height);
|
||||
}
|
||||
out << "";
|
||||
return out;
|
||||
}
|
||||
|
||||
QStringList LegacyInstance::getClassPath() const
|
||||
{
|
||||
QString launchScript;
|
||||
QString lwjgl = getNativePath();
|
||||
QStringList out =
|
||||
{
|
||||
"bin/minecraft.jar",
|
||||
lwjgl + "/lwjgl.jar",
|
||||
lwjgl + "/lwjgl_util.jar",
|
||||
lwjgl + "/jinput.jar"
|
||||
};
|
||||
return out;
|
||||
}
|
||||
|
||||
QString LegacyInstance::getMainClass() const
|
||||
{
|
||||
return "net.minecraft.client.Minecraft";
|
||||
}
|
||||
|
||||
QString LegacyInstance::getNativePath() const
|
||||
{
|
||||
return QDir(m_lwjglFolderSetting->get().toString() + "/" + lwjglVersion()).absolutePath();
|
||||
}
|
||||
|
||||
QStringList LegacyInstance::getNativeJars() const
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
QStringList LegacyInstance::processMinecraftArgs(AuthSessionPtr account) const
|
||||
{
|
||||
QStringList out;
|
||||
out.append(account->player_name);
|
||||
out.append(account->session);
|
||||
return out;
|
||||
}
|
||||
|
@ -114,11 +114,7 @@ public:
|
||||
virtual bool shouldUpdate() const override;
|
||||
virtual void setShouldUpdate(bool val) override;
|
||||
virtual std::shared_ptr<Task> createUpdateTask() override;
|
||||
|
||||
virtual std::shared_ptr<LaunchTask> createLaunchTask(AuthSessionPtr account) override;
|
||||
|
||||
virtual std::shared_ptr<Task> createJarModdingTask() override;
|
||||
|
||||
virtual QString createLaunchScript(AuthSessionPtr session) override;
|
||||
|
||||
virtual void cleanupAfterRun() override;
|
||||
@ -130,6 +126,20 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
QStringList getClassPath() const override;
|
||||
QString getMainClass() const override;
|
||||
|
||||
QStringList getNativeJars() const override;
|
||||
QString getNativePath() const override;
|
||||
|
||||
QStringList processMinecraftArgs(AuthSessionPtr account) const override;
|
||||
QStringList verboseDescription(AuthSessionPtr session) override;
|
||||
|
||||
protected:
|
||||
std::shared_ptr<LaunchStep> createMainLaunchStep(LaunchTask *parent, AuthSessionPtr session) override;
|
||||
QStringList validLaunchMethods() override;
|
||||
QString launchMethod() override;
|
||||
|
||||
protected:
|
||||
mutable std::shared_ptr<LegacyModList> jar_mod_list;
|
||||
mutable std::shared_ptr<ModList> core_mod_list;
|
||||
|
@ -14,6 +14,8 @@
|
||||
*/
|
||||
|
||||
#include <QDebug>
|
||||
#include <minecraft/launch/DirectJavaLaunch.h>
|
||||
#include <minecraft/launch/LauncherPartLaunch.h>
|
||||
#include <Env.h>
|
||||
|
||||
#include "OneSixInstance.h"
|
||||
@ -22,14 +24,7 @@
|
||||
|
||||
#include "minecraft/MinecraftProfile.h"
|
||||
#include "minecraft/VersionBuildError.h"
|
||||
#include "launch/LaunchTask.h"
|
||||
#include "launch/steps/PreLaunchCommand.h"
|
||||
#include "launch/steps/Update.h"
|
||||
#include "launch/steps/PostLaunchCommand.h"
|
||||
#include "launch/steps/TextPrint.h"
|
||||
#include "minecraft/launch/LaunchMinecraft.h"
|
||||
#include "minecraft/launch/ModMinecraftJar.h"
|
||||
#include "java/launch/CheckJava.h"
|
||||
#include "MMCZip.h"
|
||||
|
||||
#include "minecraft/AssetsUtils.h"
|
||||
@ -94,7 +89,7 @@ QString replaceTokensIn(QString text, QMap<QString, QString> with)
|
||||
return result;
|
||||
}
|
||||
|
||||
QStringList OneSixInstance::processMinecraftArgs(AuthSessionPtr session)
|
||||
QStringList OneSixInstance::processMinecraftArgs(AuthSessionPtr session) const
|
||||
{
|
||||
QString args_pattern = m_profile->getMinecraftArguments();
|
||||
for (auto tweaker : m_profile->getTweakers())
|
||||
@ -104,11 +99,16 @@ QStringList OneSixInstance::processMinecraftArgs(AuthSessionPtr session)
|
||||
|
||||
QMap<QString, QString> token_mapping;
|
||||
// yggdrasil!
|
||||
token_mapping["auth_username"] = session->username;
|
||||
token_mapping["auth_session"] = session->session;
|
||||
token_mapping["auth_access_token"] = session->access_token;
|
||||
token_mapping["auth_player_name"] = session->player_name;
|
||||
token_mapping["auth_uuid"] = session->uuid;
|
||||
if(session)
|
||||
{
|
||||
token_mapping["auth_username"] = session->username;
|
||||
token_mapping["auth_session"] = session->session;
|
||||
token_mapping["auth_access_token"] = session->access_token;
|
||||
token_mapping["auth_player_name"] = session->player_name;
|
||||
token_mapping["auth_uuid"] = session->uuid;
|
||||
token_mapping["user_properties"] = session->serializeUserProperties();
|
||||
token_mapping["user_type"] = session->user_type;
|
||||
}
|
||||
|
||||
// blatant self-promotion.
|
||||
token_mapping["profile_name"] = token_mapping["version_name"] = "MultiMC5";
|
||||
@ -127,9 +127,6 @@ QStringList OneSixInstance::processMinecraftArgs(AuthSessionPtr session)
|
||||
auto assets = m_profile->getMinecraftAssets();
|
||||
token_mapping["game_assets"] = AssetsUtils::reconstructAssets(assets->id).absolutePath();
|
||||
|
||||
token_mapping["user_properties"] = session->serializeUserProperties();
|
||||
token_mapping["user_type"] = session->user_type;
|
||||
|
||||
// 1.7.3+ assets tokens
|
||||
token_mapping["assets_root"] = absAssetsDir;
|
||||
token_mapping["assets_index_name"] = assets->id;
|
||||
@ -142,6 +139,26 @@ QStringList OneSixInstance::processMinecraftArgs(AuthSessionPtr session)
|
||||
return parts;
|
||||
}
|
||||
|
||||
QString OneSixInstance::getNativePath() const
|
||||
{
|
||||
QDir natives_dir(FS::PathCombine(instanceRoot(), "natives/"));
|
||||
return natives_dir.absolutePath();
|
||||
}
|
||||
|
||||
QString OneSixInstance::mainJarPath() const
|
||||
{
|
||||
auto jarMods = getJarMods();
|
||||
if (!jarMods.isEmpty())
|
||||
{
|
||||
return QDir(instanceRoot()).absoluteFilePath("minecraft.jar");
|
||||
}
|
||||
else
|
||||
{
|
||||
QString relpath = m_profile->getMinecraftVersion() + "/" + m_profile->getMinecraftVersion() + ".jar";
|
||||
return versionsPath().absoluteFilePath(relpath);
|
||||
}
|
||||
}
|
||||
|
||||
QString OneSixInstance::createLaunchScript(AuthSessionPtr session)
|
||||
{
|
||||
QString launchScript;
|
||||
@ -149,34 +166,7 @@ QString OneSixInstance::createLaunchScript(AuthSessionPtr session)
|
||||
if (!m_profile)
|
||||
return nullptr;
|
||||
|
||||
for(auto & mod: loaderModList()->allMods())
|
||||
{
|
||||
if(!mod.enabled())
|
||||
continue;
|
||||
if(mod.type() == Mod::MOD_FOLDER)
|
||||
continue;
|
||||
// TODO: proper implementation would need to descend into folders.
|
||||
|
||||
launchScript += "mod " + mod.filename().completeBaseName() + "\n";;
|
||||
}
|
||||
|
||||
for(auto & coremod: coreModList()->allMods())
|
||||
{
|
||||
if(!coremod.enabled())
|
||||
continue;
|
||||
if(coremod.type() == Mod::MOD_FOLDER)
|
||||
continue;
|
||||
// TODO: proper implementation would need to descend into folders.
|
||||
|
||||
launchScript += "coremod " + coremod.filename().completeBaseName() + "\n";;
|
||||
}
|
||||
|
||||
for(auto & jarmod: m_profile->getJarMods())
|
||||
{
|
||||
launchScript += "jarmod " + jarmod->originalName + " (" + jarmod->name + ")\n";
|
||||
}
|
||||
|
||||
auto mainClass = m_profile->getMainClass();
|
||||
auto mainClass = getMainClass();
|
||||
if (!mainClass.isEmpty())
|
||||
{
|
||||
launchScript += "mainClass " + mainClass + "\n";
|
||||
@ -207,6 +197,7 @@ QString OneSixInstance::createLaunchScript(AuthSessionPtr session)
|
||||
}
|
||||
|
||||
// legacy auth
|
||||
if(session)
|
||||
{
|
||||
launchScript += "userName " + session->player_name + "\n";
|
||||
launchScript += "sessionId " + session->session + "\n";
|
||||
@ -214,44 +205,21 @@ QString OneSixInstance::createLaunchScript(AuthSessionPtr session)
|
||||
|
||||
// libraries and class path.
|
||||
{
|
||||
auto libs = m_profile->getLibraries();
|
||||
|
||||
QStringList jar, native, native32, native64;
|
||||
for (auto lib : libs)
|
||||
{
|
||||
lib->getApplicableFiles(currentSystem, jar, native, native32, native64);
|
||||
}
|
||||
for(auto file: jar)
|
||||
QStringList jars, nativeJars;
|
||||
auto javaArchitecture = settings()->get("JavaArchitecture").toString();
|
||||
m_profile->getLibraryFiles(javaArchitecture, jars, nativeJars);
|
||||
for(auto file: jars)
|
||||
{
|
||||
launchScript += "cp " + file + "\n";
|
||||
}
|
||||
for(auto file: native)
|
||||
launchScript += "cp " + mainJarPath() + "\n";
|
||||
for(auto file: nativeJars)
|
||||
{
|
||||
launchScript += "ext " + file + "\n";
|
||||
}
|
||||
for(auto file: native32)
|
||||
{
|
||||
launchScript += "ext32 " + file + "\n";
|
||||
}
|
||||
for(auto file: native64)
|
||||
{
|
||||
launchScript += "ext64 " + file + "\n";
|
||||
}
|
||||
QDir natives_dir(FS::PathCombine(instanceRoot(), "natives/"));
|
||||
launchScript += "natives " + natives_dir.absolutePath() + "\n";
|
||||
auto jarMods = getJarMods();
|
||||
if (!jarMods.isEmpty())
|
||||
{
|
||||
launchScript += "cp " + QDir(instanceRoot()).absoluteFilePath("minecraft.jar") + "\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
QString relpath = m_profile->getMinecraftVersion() + "/" + m_profile->getMinecraftVersion() + ".jar";
|
||||
launchScript += "cp " + versionsPath().absoluteFilePath(relpath) + "\n";
|
||||
}
|
||||
launchScript += "natives " + getNativePath() + "\n";
|
||||
}
|
||||
|
||||
// traits. including legacyLaunch and others ;)
|
||||
for (auto trait : m_profile->getTraits())
|
||||
{
|
||||
launchScript += "traits " + trait + "\n";
|
||||
@ -260,58 +228,139 @@ QString OneSixInstance::createLaunchScript(AuthSessionPtr session)
|
||||
return launchScript;
|
||||
}
|
||||
|
||||
std::shared_ptr<LaunchTask> OneSixInstance::createLaunchTask(AuthSessionPtr session)
|
||||
QStringList OneSixInstance::verboseDescription(AuthSessionPtr session)
|
||||
{
|
||||
auto process = LaunchTask::create(std::dynamic_pointer_cast<MinecraftInstance>(getSharedPtr()));
|
||||
auto pptr = process.get();
|
||||
QStringList out;
|
||||
out << "Main Class:" << " " + getMainClass() << "";
|
||||
out << "Native path:" << " " + getNativePath() << "";
|
||||
|
||||
// print a header
|
||||
|
||||
auto alltraits = traits();
|
||||
if(alltraits.size())
|
||||
{
|
||||
process->appendStep(std::make_shared<TextPrint>(pptr, "Minecraft folder is:\n" + minecraftRoot() + "\n\n", MessageLevel::MultiMC));
|
||||
out << "Traits:";
|
||||
for (auto trait : alltraits)
|
||||
{
|
||||
out << "traits " + trait;
|
||||
}
|
||||
out << "";
|
||||
}
|
||||
|
||||
// libraries and class path.
|
||||
{
|
||||
auto step = std::make_shared<CheckJava>(pptr);
|
||||
process->appendStep(step);
|
||||
out << "Libraries:";
|
||||
QStringList jars, nativeJars;
|
||||
auto javaArchitecture = settings()->get("JavaArchitecture").toString();
|
||||
m_profile->getLibraryFiles(javaArchitecture, jars, nativeJars);
|
||||
auto printLibFile = [&](const QString & path)
|
||||
{
|
||||
QFileInfo info(path);
|
||||
if(info.exists())
|
||||
{
|
||||
out << " " + path;
|
||||
}
|
||||
else
|
||||
{
|
||||
out << " " + path + " (missing)";
|
||||
}
|
||||
};
|
||||
for(auto file: jars)
|
||||
{
|
||||
printLibFile(file);
|
||||
}
|
||||
printLibFile(mainJarPath());
|
||||
for(auto file: nativeJars)
|
||||
{
|
||||
printLibFile(file);
|
||||
}
|
||||
out << "";
|
||||
}
|
||||
// run pre-launch command if that's needed
|
||||
if(getPreLaunchCommand().size())
|
||||
|
||||
if(loaderModList()->size())
|
||||
{
|
||||
auto step = std::make_shared<PreLaunchCommand>(pptr);
|
||||
out << "Mods:";
|
||||
for(auto & mod: loaderModList()->allMods())
|
||||
{
|
||||
if(!mod.enabled())
|
||||
continue;
|
||||
if(mod.type() == Mod::MOD_FOLDER)
|
||||
continue;
|
||||
// TODO: proper implementation would need to descend into folders.
|
||||
|
||||
out << " " + mod.filename().completeBaseName();
|
||||
}
|
||||
out << "";
|
||||
}
|
||||
|
||||
if(coreModList()->size())
|
||||
{
|
||||
out << "Core Mods:";
|
||||
for(auto & coremod: coreModList()->allMods())
|
||||
{
|
||||
if(!coremod.enabled())
|
||||
continue;
|
||||
if(coremod.type() == Mod::MOD_FOLDER)
|
||||
continue;
|
||||
// TODO: proper implementation would need to descend into folders.
|
||||
|
||||
out << " " + coremod.filename().completeBaseName();
|
||||
}
|
||||
out << "";
|
||||
}
|
||||
|
||||
auto & jarMods = m_profile->getJarMods();
|
||||
if(jarMods.size())
|
||||
{
|
||||
out << "Jar Mods:";
|
||||
for(auto & jarmod: jarMods)
|
||||
{
|
||||
out << " " + jarmod->originalName + " (" + jarmod->name + ")";
|
||||
}
|
||||
out << "";
|
||||
}
|
||||
|
||||
auto params = processMinecraftArgs(nullptr);
|
||||
out << "Params:";
|
||||
out << " " + params.join(' ');
|
||||
out << "";
|
||||
|
||||
QString windowParams;
|
||||
if (settings()->get("LaunchMaximized").toBool())
|
||||
{
|
||||
out << "Window size: max (if available)";
|
||||
}
|
||||
else
|
||||
{
|
||||
auto width = settings()->get("MinecraftWinWidth").toInt();
|
||||
auto height = settings()->get("MinecraftWinHeight").toInt();
|
||||
out << "Window size: " + QString::number(width) + " x " + QString::number(height);
|
||||
}
|
||||
out << "";
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
std::shared_ptr<LaunchStep> OneSixInstance::createMainLaunchStep(LaunchTask * parent, AuthSessionPtr session)
|
||||
{
|
||||
auto method = launchMethod();
|
||||
if(method == "LauncherPart")
|
||||
{
|
||||
auto step = std::make_shared<LauncherPartLaunch>(parent);
|
||||
step->setAuthSession(session);
|
||||
step->setWorkingDirectory(minecraftRoot());
|
||||
process->appendStep(step);
|
||||
return step;
|
||||
}
|
||||
// if we aren't in offline mode,.
|
||||
if(session->status != AuthSession::PlayableOffline)
|
||||
else if (method == "DirectJava")
|
||||
{
|
||||
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);
|
||||
}
|
||||
// actually launch the game
|
||||
{
|
||||
auto step = std::make_shared<LaunchMinecraft>(pptr);
|
||||
auto step = std::make_shared<DirectJavaLaunch>(parent);
|
||||
step->setWorkingDirectory(minecraftRoot());
|
||||
step->setAuthSession(session);
|
||||
process->appendStep(step);
|
||||
return 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;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
std::shared_ptr<Task> OneSixInstance::createJarModdingTask()
|
||||
{
|
||||
class JarModTask : public Task
|
||||
@ -595,3 +644,30 @@ QString OneSixInstance::typeName() const
|
||||
{
|
||||
return tr("OneSix");
|
||||
}
|
||||
|
||||
QStringList OneSixInstance::validLaunchMethods()
|
||||
{
|
||||
return {"LauncherPart", "DirectJava"};
|
||||
}
|
||||
|
||||
QStringList OneSixInstance::getClassPath() const
|
||||
{
|
||||
QStringList jars, nativeJars;
|
||||
auto javaArchitecture = settings()->get("JavaArchitecture").toString();
|
||||
m_profile->getLibraryFiles(javaArchitecture, jars, nativeJars);
|
||||
jars.append(mainJarPath());
|
||||
return jars;
|
||||
}
|
||||
|
||||
QString OneSixInstance::getMainClass() const
|
||||
{
|
||||
return m_profile->getMainClass();
|
||||
}
|
||||
|
||||
QStringList OneSixInstance::getNativeJars() const
|
||||
{
|
||||
QStringList jars, nativeJars;
|
||||
auto javaArchitecture = settings()->get("JavaArchitecture").toString();
|
||||
m_profile->getLibraryFiles(javaArchitecture, jars, nativeJars);
|
||||
return nativeJars;
|
||||
}
|
||||
|
@ -53,10 +53,9 @@ public:
|
||||
virtual QString instanceConfigFolder() const override;
|
||||
|
||||
virtual std::shared_ptr<Task> createUpdateTask() override;
|
||||
virtual std::shared_ptr<LaunchTask> createLaunchTask(AuthSessionPtr account) override;
|
||||
virtual std::shared_ptr<Task> createJarModdingTask() override;
|
||||
|
||||
virtual QString createLaunchScript(AuthSessionPtr session) override;
|
||||
QStringList verboseDescription(AuthSessionPtr session) override;
|
||||
|
||||
virtual void cleanupAfterRun() override;
|
||||
|
||||
@ -99,11 +98,23 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
QStringList getClassPath() const override;
|
||||
QString getMainClass() const override;
|
||||
|
||||
QStringList getNativeJars() const override;
|
||||
QString getNativePath() const override;
|
||||
|
||||
QStringList processMinecraftArgs(AuthSessionPtr account) const override;
|
||||
|
||||
protected:
|
||||
std::shared_ptr<LaunchStep> createMainLaunchStep(LaunchTask *parent, AuthSessionPtr session) override;
|
||||
QStringList validLaunchMethods() override;
|
||||
|
||||
signals:
|
||||
void versionReloaded();
|
||||
|
||||
private:
|
||||
QStringList processMinecraftArgs(AuthSessionPtr account);
|
||||
QString mainJarPath() const;
|
||||
|
||||
protected:
|
||||
std::shared_ptr<MinecraftProfile> m_profile;
|
||||
|
@ -524,11 +524,15 @@ void MultiMC::initGlobalSettings(bool test_mode)
|
||||
// Java Settings
|
||||
m_settings->registerSetting("JavaPath", "");
|
||||
m_settings->registerSetting("JavaTimestamp", 0);
|
||||
m_settings->registerSetting("JavaArchitecture", "");
|
||||
m_settings->registerSetting("JavaVersion", "");
|
||||
m_settings->registerSetting("LastHostname", "");
|
||||
m_settings->registerSetting("JavaDetectionHack", "");
|
||||
m_settings->registerSetting("JvmArgs", "");
|
||||
|
||||
// Minecraft launch method
|
||||
m_settings->registerSetting("MCLaunchMethod", "LauncherPart");
|
||||
|
||||
// Wrapper command for launch
|
||||
m_settings->registerSetting("WrapperCommand", "");
|
||||
|
||||
|
@ -17,7 +17,6 @@ set(SRC
|
||||
# legacy applet wrapper thing.
|
||||
# The launcher has to be there for silly FML/Forge relauncher.
|
||||
net/minecraft/Launcher.java
|
||||
org/multimc/legacy/LegacyLauncher.java
|
||||
org/multimc/LegacyFrame.java
|
||||
|
||||
# onesix launcher
|
||||
|
@ -14,7 +14,6 @@ package org.multimc;/*
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import org.multimc.legacy.LegacyLauncher;
|
||||
import org.multimc.onesix.OneSixLauncher;
|
||||
import org.simplericity.macify.eawt.Application;
|
||||
import org.simplericity.macify.eawt.DefaultApplication;
|
||||
@ -83,13 +82,6 @@ public class EntryPoint
|
||||
|
||||
if(command.equals("launcher"))
|
||||
{
|
||||
if(param.equals("legacy"))
|
||||
{
|
||||
m_launcher = new LegacyLauncher();
|
||||
Utils.log("Using legacy launcher.");
|
||||
Utils.log();
|
||||
return Action.Proceed;
|
||||
}
|
||||
if(param.equals("onesix"))
|
||||
{
|
||||
m_launcher = new OneSixLauncher();
|
||||
|
@ -186,95 +186,5 @@ public class Utils
|
||||
{
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
/**
|
||||
* Pushes bytes from in to out. Closes both streams no matter what.
|
||||
* @param in the input stream
|
||||
* @param out the output stream
|
||||
* @throws IOException
|
||||
*/
|
||||
private static void copyStream(InputStream in, OutputStream out) throws IOException
|
||||
{
|
||||
try
|
||||
{
|
||||
byte[] buffer = new byte[4096];
|
||||
int len;
|
||||
|
||||
while((len = in.read(buffer)) >= 0)
|
||||
out.write(buffer, 0, len);
|
||||
} finally
|
||||
{
|
||||
in.close();
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace a 'target' string 'suffix' with 'replacement'
|
||||
*/
|
||||
public static String replaceSuffix (String target, String suffix, String replacement)
|
||||
{
|
||||
if (!target.endsWith(suffix))
|
||||
{
|
||||
return target;
|
||||
}
|
||||
String prefix = target.substring(0, target.length() - suffix.length());
|
||||
return prefix + replacement;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unzip zip file with natives 'source' into the folder 'targetFolder'
|
||||
*
|
||||
* Contains a hack for OSX. Yay.
|
||||
* @param source
|
||||
* @param targetFolder
|
||||
* @throws IOException
|
||||
*/
|
||||
public static void unzipNatives(File source, File targetFolder) throws IOException
|
||||
{
|
||||
ZipFile zip = new ZipFile(source);
|
||||
|
||||
boolean applyHacks = false;
|
||||
String[] javaVersionElements = System.getProperty("java.version").split("[.\\-+]");
|
||||
int major = Integer.parseInt(javaVersionElements[0]);
|
||||
if(major == 1)
|
||||
{
|
||||
major = Integer.parseInt(javaVersionElements[1]);
|
||||
}
|
||||
if (major >= 8)
|
||||
{
|
||||
applyHacks = true;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Enumeration entries = zip.entries();
|
||||
|
||||
while (entries.hasMoreElements())
|
||||
{
|
||||
ZipEntry entry = (ZipEntry) entries.nextElement();
|
||||
|
||||
String entryName = entry.getName();
|
||||
String fileName = entryName;
|
||||
if(applyHacks)
|
||||
{
|
||||
fileName = replaceSuffix(entryName, ".jnilib", ".dylib");
|
||||
}
|
||||
File targetFile = new File(targetFolder, fileName);
|
||||
if (targetFile.getParentFile() != null)
|
||||
{
|
||||
targetFile.getParentFile().mkdirs();
|
||||
}
|
||||
|
||||
if (entry.isDirectory())
|
||||
continue;
|
||||
|
||||
copyStream(zip.getInputStream(entry), new BufferedOutputStream(new FileOutputStream(targetFile)));
|
||||
}
|
||||
} finally
|
||||
{
|
||||
zip.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,175 +0,0 @@
|
||||
package org.multimc.legacy;/*
|
||||
* Copyright 2012-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.
|
||||
*/
|
||||
|
||||
import org.multimc.*;
|
||||
|
||||
import java.applet.Applet;
|
||||
import java.awt.*;
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Field;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
|
||||
public class LegacyLauncher implements Launcher
|
||||
{
|
||||
@Override
|
||||
public int launch(ParamBucket params)
|
||||
{
|
||||
String userName, sessionId, windowTitle, windowParams, lwjgl;
|
||||
String mainClass = "net.minecraft.client.Minecraft";
|
||||
try
|
||||
{
|
||||
userName = params.first("userName");
|
||||
sessionId = params.first("sessionId");
|
||||
windowTitle = params.first("windowTitle");
|
||||
windowParams = params.first("windowParams");
|
||||
lwjgl = params.first("lwjgl");
|
||||
} catch (NotFoundException e)
|
||||
{
|
||||
System.err.println("Not enough arguments.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
String cwd = System.getProperty("user.dir");
|
||||
Dimension winSize = new Dimension(854, 480);
|
||||
boolean maximize = false;
|
||||
|
||||
String[] dimStrings = windowParams.split("x");
|
||||
|
||||
if (windowParams.equalsIgnoreCase("max"))
|
||||
{
|
||||
maximize = true;
|
||||
}
|
||||
else if (dimStrings.length == 2)
|
||||
{
|
||||
try
|
||||
{
|
||||
winSize = new Dimension(Integer.parseInt(dimStrings[0]), Integer.parseInt(dimStrings[1]));
|
||||
} catch (NumberFormatException ignored) {}
|
||||
}
|
||||
|
||||
File binDir = new File(cwd, "bin");
|
||||
File lwjglDir;
|
||||
if (lwjgl.equalsIgnoreCase("Mojang"))
|
||||
{
|
||||
lwjglDir = binDir;
|
||||
}
|
||||
else
|
||||
{
|
||||
lwjglDir = new File(lwjgl);
|
||||
}
|
||||
|
||||
URL[] classpath;
|
||||
{
|
||||
try
|
||||
{
|
||||
classpath = new URL[]
|
||||
{
|
||||
new File(binDir, "minecraft.jar").toURI().toURL(),
|
||||
new File(lwjglDir, "lwjgl.jar").toURI().toURL(),
|
||||
new File(lwjglDir, "lwjgl_util.jar").toURI().toURL(),
|
||||
new File(lwjglDir, "jinput.jar").toURI().toURL(),
|
||||
};
|
||||
} catch (MalformedURLException e)
|
||||
{
|
||||
System.err.println("Class path entry is badly formed:");
|
||||
e.printStackTrace(System.err);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
String nativesDir = new File(lwjglDir, "natives").toString();
|
||||
|
||||
System.setProperty("org.lwjgl.librarypath", nativesDir);
|
||||
System.setProperty("net.java.games.input.librarypath", nativesDir);
|
||||
|
||||
// print the pretty things
|
||||
{
|
||||
Utils.log("Main Class:");
|
||||
Utils.log(" " + mainClass);
|
||||
Utils.log();
|
||||
|
||||
Utils.log("Class Path:");
|
||||
for (URL s : classpath)
|
||||
{
|
||||
Utils.log(" " + s);
|
||||
}
|
||||
Utils.log();
|
||||
|
||||
Utils.log("Native Path:");
|
||||
Utils.log(" " + nativesDir);
|
||||
Utils.log();
|
||||
}
|
||||
|
||||
URLClassLoader cl = new URLClassLoader(classpath, LegacyLauncher.class.getClassLoader());
|
||||
|
||||
// Get the Minecraft Class and set the base folder
|
||||
Class<?> mc;
|
||||
try
|
||||
{
|
||||
mc = cl.loadClass(mainClass);
|
||||
|
||||
Field f = Utils.getMCPathField(mc);
|
||||
|
||||
if (f == null)
|
||||
{
|
||||
System.err.println("Could not find Minecraft path field. Launch failed.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
f.setAccessible(true);
|
||||
f.set(null, new File(cwd));
|
||||
} catch (Exception e)
|
||||
{
|
||||
System.err.println("Could not set base folder. Failed to find/access Minecraft main class:");
|
||||
e.printStackTrace(System.err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
System.setProperty("minecraft.applet.TargetDirectory", cwd);
|
||||
|
||||
String[] mcArgs = new String[2];
|
||||
mcArgs[0] = userName;
|
||||
mcArgs[1] = sessionId;
|
||||
|
||||
Utils.log("Launching with applet wrapper...");
|
||||
try
|
||||
{
|
||||
Class<?> MCAppletClass = cl.loadClass("net.minecraft.client.MinecraftApplet");
|
||||
Applet mcappl = (Applet) MCAppletClass.newInstance();
|
||||
LegacyFrame mcWindow = new LegacyFrame(windowTitle);
|
||||
mcWindow.start(mcappl, userName, sessionId, winSize, maximize);
|
||||
} catch (Exception e)
|
||||
{
|
||||
Utils.log("Applet wrapper failed:", "Error");
|
||||
e.printStackTrace(System.err);
|
||||
Utils.log();
|
||||
Utils.log("Falling back to compatibility mode.");
|
||||
try
|
||||
{
|
||||
mc.getMethod("main", String[].class).invoke(null, (Object) mcArgs);
|
||||
} catch (Exception e1)
|
||||
{
|
||||
Utils.log("Failed to invoke the Minecraft main class:", "Fatal");
|
||||
e1.printStackTrace(System.err);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
@ -30,9 +30,6 @@ public class OneSixLauncher implements Launcher
|
||||
{
|
||||
// parameters, separated from ParamBucket
|
||||
private List<String> libraries;
|
||||
private List<String> extlibs;
|
||||
private List<String> extlibs32;
|
||||
private List<String> extlibs64;
|
||||
private List<String> mcparams;
|
||||
private List<String> mods;
|
||||
private List<String> jarmods;
|
||||
@ -56,28 +53,9 @@ public class OneSixLauncher implements Launcher
|
||||
private void processParams(ParamBucket params) throws NotFoundException
|
||||
{
|
||||
libraries = params.all("cp");
|
||||
extlibs = params.allSafe("ext", new ArrayList<String>());
|
||||
extlibs32 = params.allSafe("ext32", new ArrayList<String>());
|
||||
extlibs64 = params.allSafe("ext64", new ArrayList<String>());
|
||||
|
||||
// Unify the extracted native libs according to actual system architecture
|
||||
String property = System.getProperty("os.arch");
|
||||
boolean is_64 = property.equalsIgnoreCase("x86_64") || property.equalsIgnoreCase("amd64");
|
||||
if(is_64)
|
||||
{
|
||||
extlibs.addAll(extlibs64);
|
||||
}
|
||||
else
|
||||
{
|
||||
extlibs.addAll(extlibs32);
|
||||
}
|
||||
|
||||
mcparams = params.allSafe("param", new ArrayList<String>() );
|
||||
mainClass = params.firstSafe("mainClass", "net.minecraft.client.Minecraft");
|
||||
appletClass = params.firstSafe("appletClass", "net.minecraft.client.MinecraftApplet");
|
||||
mods = params.allSafe("mod", new ArrayList<String>());
|
||||
jarmods = params.allSafe("jarmod", new ArrayList<String>());
|
||||
coremods = params.allSafe("coremod", new ArrayList<String>());
|
||||
traits = params.allSafe("traits", new ArrayList<String>());
|
||||
nativePath = params.first("natives");
|
||||
|
||||
@ -105,75 +83,6 @@ public class OneSixLauncher implements Launcher
|
||||
}
|
||||
}
|
||||
|
||||
private void printStats()
|
||||
{
|
||||
Utils.log("Main Class:");
|
||||
Utils.log(" " + mainClass);
|
||||
Utils.log();
|
||||
|
||||
Utils.log("Native path:");
|
||||
Utils.log(" " + nativePath);
|
||||
Utils.log();
|
||||
|
||||
Utils.log("Traits:");
|
||||
Utils.log(" " + traits);
|
||||
Utils.log();
|
||||
|
||||
Utils.log("Libraries:");
|
||||
for (String s : libraries)
|
||||
{
|
||||
File f = new File(s);
|
||||
if (f.exists())
|
||||
{
|
||||
Utils.log(" " + s);
|
||||
}
|
||||
else
|
||||
{
|
||||
Utils.log(" " + s + " (missing)", "Warning");
|
||||
}
|
||||
}
|
||||
Utils.log();
|
||||
|
||||
if(mods.size() > 0)
|
||||
{
|
||||
Utils.log("Mods:");
|
||||
for (String s : mods)
|
||||
{
|
||||
Utils.log(" " + s);
|
||||
}
|
||||
Utils.log();
|
||||
}
|
||||
|
||||
if(coremods.size() > 0)
|
||||
{
|
||||
Utils.log("Core Mods:");
|
||||
for (String s : coremods)
|
||||
{
|
||||
Utils.log(" " + s);
|
||||
}
|
||||
Utils.log();
|
||||
}
|
||||
|
||||
if(jarmods.size() > 0)
|
||||
{
|
||||
Utils.log("Jar Mods:");
|
||||
for (String s : jarmods)
|
||||
{
|
||||
Utils.log(" " + s);
|
||||
}
|
||||
Utils.log();
|
||||
}
|
||||
|
||||
Utils.log("Params:");
|
||||
Utils.log(" " + mcparams.toString());
|
||||
Utils.log();
|
||||
if(maximize)
|
||||
Utils.log("Window size: max (if available)");
|
||||
else
|
||||
Utils.log("Window size: " + Integer.toString(winSize.width) + " x " + Integer.toString(winSize.height));
|
||||
Utils.log();
|
||||
}
|
||||
|
||||
int legacyLaunch()
|
||||
{
|
||||
// Get the Minecraft Class and set the base folder
|
||||
@ -310,27 +219,6 @@ public class OneSixLauncher implements Launcher
|
||||
return -1;
|
||||
}
|
||||
|
||||
// print the pretty things
|
||||
printStats();
|
||||
|
||||
// extract native libs (depending on platform here... java!)
|
||||
Utils.log("Preparing native libraries...");
|
||||
for(String extlib: extlibs)
|
||||
{
|
||||
try
|
||||
{
|
||||
File extlibf = new File(extlib);
|
||||
Utils.log("Extracting " + extlibf.getName());
|
||||
Utils.unzipNatives(extlibf, new File(nativePath));
|
||||
} catch (IOException e)
|
||||
{
|
||||
System.err.println("Failed to extract native library:");
|
||||
e.printStackTrace(System.err);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
Utils.log();
|
||||
|
||||
// set the native libs path... the brute force way
|
||||
try
|
||||
{
|
||||
|
@ -68,6 +68,7 @@ void WonkoClient::initGlobalSettings()
|
||||
// Java Settings
|
||||
m_settings->registerSetting("JavaPath", "");
|
||||
m_settings->registerSetting("JavaTimestamp", 0);
|
||||
m_settings->registerSetting("JavaArchitecture", "");
|
||||
m_settings->registerSetting("JavaVersion", "");
|
||||
m_settings->registerSetting("LastHostname", "");
|
||||
m_settings->registerSetting("JavaDetectionHack", "");
|
||||
@ -79,4 +80,7 @@ void WonkoClient::initGlobalSettings()
|
||||
// Custom Commands
|
||||
m_settings->registerSetting({"PreLaunchCommand", "PreLaunchCmd"}, "");
|
||||
m_settings->registerSetting({"PostExitCommand", "PostExitCmd"}, "");
|
||||
|
||||
// Minecraft launch method
|
||||
m_settings->registerSetting("MCLaunchMethod", "LauncherPart");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user