Merge pull request #5125 from arthomnix/feature/singleplayer-quickplay

NOISSUE Add support for launching worlds directly via Quick Play
This commit is contained in:
Petr Mrázek 2023-05-16 21:12:28 +02:00 committed by GitHub
commit d05a9a6a5f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
33 changed files with 566 additions and 166 deletions

View File

@ -242,7 +242,11 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
// --server // --server
parser.addOption("server"); parser.addOption("server");
parser.addShortOpt("server", 's'); parser.addShortOpt("server", 's');
parser.addDocumentation("server", "Join the specified server on launch (only valid in combination with --launch)"); parser.addDocumentation("server", "Join the specified server on launch (only valid in combination with --launch, mutually exclusive with --world)");
// --world
parser.addOption("world");
parser.addShortOpt("world", 'w');
parser.addDocumentation("world", "Join the singleplayer world with the specified folder name on launch (only valid in combination with --launch, mutually exclusive with --server, only works with Minecraft 23w14a and later)");
// --profile // --profile
parser.addOption("profile"); parser.addOption("profile");
parser.addShortOpt("profile", 'a'); parser.addShortOpt("profile", 'a');
@ -297,6 +301,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
} }
m_instanceIdToLaunch = args["launch"].toString(); m_instanceIdToLaunch = args["launch"].toString();
m_serverToJoin = args["server"].toString(); m_serverToJoin = args["server"].toString();
m_worldToJoin = args["world"].toString();
m_profileToUse = args["profile"].toString(); m_profileToUse = args["profile"].toString();
if(args["offline"].toBool()) { if(args["offline"].toBool()) {
m_offline = true; m_offline = true;
@ -367,6 +372,14 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
return; return;
} }
// --world and --server can't be used together
if(!m_worldToJoin.isEmpty() && !m_serverToJoin.isEmpty())
{
std::cerr << "--server and --world are mutually exclusive!" << std::endl;
m_status = Application::Failed;
return;
}
// all the things invalid when NOT trying to --launch // all the things invalid when NOT trying to --launch
if(m_instanceIdToLaunch.isEmpty()) { if(m_instanceIdToLaunch.isEmpty()) {
if(!m_serverToJoin.isEmpty()) if(!m_serverToJoin.isEmpty())
@ -376,6 +389,13 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
return; return;
} }
if(!m_worldToJoin.isEmpty())
{
std::cerr << "--world can only be used in combination with --launch!" << std::endl;
m_status = Application::Failed;
return;
}
if(!m_profileToUse.isEmpty()) if(!m_profileToUse.isEmpty())
{ {
std::cerr << "--account can only be used in combination with --launch!" << std::endl; std::cerr << "--account can only be used in combination with --launch!" << std::endl;
@ -507,6 +527,10 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
{ {
launch.args["server"] = m_serverToJoin; launch.args["server"] = m_serverToJoin;
} }
if(!m_worldToJoin.isEmpty())
{
launch.args["world"] = m_worldToJoin;
}
if(!m_profileToUse.isEmpty()) if(!m_profileToUse.isEmpty())
{ {
launch.args["profile"] = m_profileToUse; launch.args["profile"] = m_profileToUse;
@ -599,6 +623,10 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
{ {
qDebug() << "Address of server to join :" << m_serverToJoin; qDebug() << "Address of server to join :" << m_serverToJoin;
} }
if(!m_worldToJoin.isEmpty())
{
qDebug() << "Name of world to join :" << m_worldToJoin;
}
qDebug() << "<> Paths set."; qDebug() << "<> Paths set.";
} }
@ -1070,7 +1098,7 @@ void Application::performMainStartupAction()
auto inst = instances()->getInstanceById(m_instanceIdToLaunch); auto inst = instances()->getInstanceById(m_instanceIdToLaunch);
if(inst) if(inst)
{ {
MinecraftServerTargetPtr serverToJoin = nullptr; QuickPlayTargetPtr serverOrWorldToJoin = nullptr;
MinecraftAccountPtr accountToUse = nullptr; MinecraftAccountPtr accountToUse = nullptr;
bool offline = m_offline; bool offline = m_offline;
@ -1078,10 +1106,16 @@ void Application::performMainStartupAction()
if(!m_serverToJoin.isEmpty()) if(!m_serverToJoin.isEmpty())
{ {
// FIXME: validate the server string // FIXME: validate the server string
serverToJoin.reset(new MinecraftServerTarget(MinecraftServerTarget::parse(m_serverToJoin))); serverOrWorldToJoin.reset(new QuickPlayTarget(QuickPlayTarget::parseMultiplayer(m_serverToJoin)));
qDebug() << " Launching with server" << m_serverToJoin; qDebug() << " Launching with server" << m_serverToJoin;
} }
if(!m_worldToJoin.isEmpty())
{
serverOrWorldToJoin.reset(new QuickPlayTarget(QuickPlayTarget::parseSingleplayer(m_worldToJoin)));
qDebug() << " Launching with world" << m_worldToJoin;
}
if(!m_profileToUse.isEmpty()) if(!m_profileToUse.isEmpty())
{ {
accountToUse = accounts()->getAccountByProfileName(m_profileToUse); accountToUse = accounts()->getAccountByProfileName(m_profileToUse);
@ -1091,7 +1125,7 @@ void Application::performMainStartupAction()
qDebug() << " Launching with account" << m_profileToUse; qDebug() << " Launching with account" << m_profileToUse;
} }
launch(inst, !offline, nullptr, serverToJoin, accountToUse, m_offlineName); launch(inst, !offline, nullptr, serverOrWorldToJoin, accountToUse, m_offlineName);
return; return;
} }
} }
@ -1163,6 +1197,7 @@ void Application::messageReceived(const QByteArray& message)
{ {
QString id = received.args["id"]; QString id = received.args["id"];
QString server = received.args["server"]; QString server = received.args["server"];
QString world = received.args["world"];
QString profile = received.args["profile"]; QString profile = received.args["profile"];
bool offline = received.args["offline_enabled"] == "true"; bool offline = received.args["offline_enabled"] == "true";
QString offlineName = received.args["offline_name"]; QString offlineName = received.args["offline_name"];
@ -1180,9 +1215,11 @@ void Application::messageReceived(const QByteArray& message)
return; return;
} }
MinecraftServerTargetPtr serverObject = nullptr; QuickPlayTargetPtr quickPlayTarget = nullptr;
if(!server.isEmpty()) { if(!server.isEmpty()) {
serverObject = std::make_shared<MinecraftServerTarget>(MinecraftServerTarget::parse(server)); quickPlayTarget = std::make_shared<QuickPlayTarget>(QuickPlayTarget::parseMultiplayer(server));
} else if(!world.isEmpty()) {
quickPlayTarget = std::make_shared<QuickPlayTarget>(QuickPlayTarget::parseSingleplayer(world));
} }
MinecraftAccountPtr accountObject; MinecraftAccountPtr accountObject;
@ -1198,7 +1235,7 @@ void Application::messageReceived(const QByteArray& message)
instance, instance,
!offline, !offline,
nullptr, nullptr,
serverObject, quickPlayTarget,
accountObject, accountObject,
offlineName offlineName
); );
@ -1297,7 +1334,7 @@ bool Application::launch(
InstancePtr instance, InstancePtr instance,
bool online, bool online,
BaseProfilerFactory *profiler, BaseProfilerFactory *profiler,
MinecraftServerTargetPtr serverToJoin, QuickPlayTargetPtr quickPlayTarget,
MinecraftAccountPtr accountToUse, MinecraftAccountPtr accountToUse,
const QString& offlineName const QString& offlineName
) { ) {
@ -1321,7 +1358,7 @@ bool Application::launch(
controller->setInstance(instance); controller->setInstance(instance);
controller->setOnline(online); controller->setOnline(online);
controller->setProfiler(profiler); controller->setProfiler(profiler);
controller->setServerToJoin(serverToJoin); controller->setQuickPlayTarget(quickPlayTarget);
controller->setAccountToUse(accountToUse); controller->setAccountToUse(accountToUse);
controller->setOfflineName(offlineName); controller->setOfflineName(offlineName);
if(window) if(window)

View File

@ -11,7 +11,7 @@
#include <BaseInstance.h> #include <BaseInstance.h>
#include "minecraft/launch/MinecraftServerTarget.h" #include "minecraft/launch/QuickPlayTarget.h"
class LaunchController; class LaunchController;
class LocalPeer; class LocalPeer;
@ -153,7 +153,7 @@ public slots:
InstancePtr instance, InstancePtr instance,
bool online = true, bool online = true,
BaseProfilerFactory *profiler = nullptr, BaseProfilerFactory *profiler = nullptr,
MinecraftServerTargetPtr serverToJoin = nullptr, QuickPlayTargetPtr quickPlayTarget = nullptr,
MinecraftAccountPtr accountToUse = nullptr, MinecraftAccountPtr accountToUse = nullptr,
const QString &offlineName = QString() const QString &offlineName = QString()
); );
@ -234,6 +234,7 @@ private:
public: public:
QString m_instanceIdToLaunch; QString m_instanceIdToLaunch;
QString m_serverToJoin; QString m_serverToJoin;
QString m_worldToJoin;
QString m_profileToUse; QString m_profileToUse;
bool m_offline = false; bool m_offline = false;
QString m_offlineName; QString m_offlineName;

View File

@ -1,4 +1,4 @@
/* Copyright 2013-2021 MultiMC Contributors /* Copyright 2013-2023 MultiMC Contributors
* Copyright 2022 Jamie Mansfield <jmansfield@cadixdev.org> * Copyright 2022 Jamie Mansfield <jmansfield@cadixdev.org>
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -33,7 +33,7 @@
#include "net/Mode.h" #include "net/Mode.h"
#include "minecraft/launch/MinecraftServerTarget.h" #include "minecraft/launch/QuickPlayTarget.h"
class QDir; class QDir;
class Task; class Task;
@ -161,7 +161,7 @@ public:
/// returns a valid launcher (task container) /// returns a valid launcher (task container)
virtual shared_qobject_ptr<LaunchTask> createLaunchTask( virtual shared_qobject_ptr<LaunchTask> createLaunchTask(
AuthSessionPtr account, MinecraftServerTargetPtr serverToJoin) = 0; AuthSessionPtr account, QuickPlayTargetPtr quickPlayTarget) = 0;
/// returns the current launch task (if any) /// returns the current launch task (if any)
shared_qobject_ptr<LaunchTask> getLaunchTask(); shared_qobject_ptr<LaunchTask> getLaunchTask();
@ -239,7 +239,7 @@ public:
/** /**
* 'print' a verbose description of the instance into a QStringList * 'print' a verbose description of the instance into a QStringList
*/ */
virtual QStringList verboseDescription(AuthSessionPtr session, MinecraftServerTargetPtr serverToJoin) = 0; virtual QStringList verboseDescription(AuthSessionPtr session, QuickPlayTargetPtr quickPlayTarget) = 0;
Status currentStatus() const; Status currentStatus() const;

View File

@ -269,8 +269,8 @@ set(MINECRAFT_SOURCES
minecraft/launch/ExtractNatives.h minecraft/launch/ExtractNatives.h
minecraft/launch/LauncherPartLaunch.cpp minecraft/launch/LauncherPartLaunch.cpp
minecraft/launch/LauncherPartLaunch.h minecraft/launch/LauncherPartLaunch.h
minecraft/launch/MinecraftServerTarget.cpp minecraft/launch/QuickPlayTarget.cpp
minecraft/launch/MinecraftServerTarget.h minecraft/launch/QuickPlayTarget.h
minecraft/launch/PrintInstanceInfo.cpp minecraft/launch/PrintInstanceInfo.cpp
minecraft/launch/PrintInstanceInfo.h minecraft/launch/PrintInstanceInfo.h
minecraft/launch/ReconstructAssets.cpp minecraft/launch/ReconstructAssets.cpp

View File

@ -45,7 +45,7 @@ public:
values.append(new TexturePackPage(onesix.get())); values.append(new TexturePackPage(onesix.get()));
values.append(new ShaderPackPage(onesix.get())); values.append(new ShaderPackPage(onesix.get()));
values.append(new NotesPage(onesix.get())); values.append(new NotesPage(onesix.get()));
values.append(new WorldListPage(onesix.get(), onesix->worldList())); values.append(new WorldListPage(onesix, onesix->worldList()));
values.append(new ServersPage(onesix)); values.append(new ServersPage(onesix));
// values.append(new GameOptionsPage(onesix.get())); // values.append(new GameOptionsPage(onesix.get()));
values.append(new ScreenshotsPage(FS::PathCombine(onesix->gameRoot(), "screenshots"))); values.append(new ScreenshotsPage(FS::PathCombine(onesix->gameRoot(), "screenshots")));
@ -56,7 +56,7 @@ public:
{ {
values.append(new LegacyUpgradePage(legacy)); values.append(new LegacyUpgradePage(legacy));
values.append(new NotesPage(legacy.get())); values.append(new NotesPage(legacy.get()));
values.append(new WorldListPage(legacy.get(), legacy->worldList())); values.append(new WorldListPage(legacy, legacy->worldList()));
values.append(new ScreenshotsPage(FS::PathCombine(legacy->gameRoot(), "screenshots"))); values.append(new ScreenshotsPage(FS::PathCombine(legacy->gameRoot(), "screenshots")));
} }
auto logMatcher = inst->getLogFileMatcher(); auto logMatcher = inst->getLogFileMatcher();

View File

@ -321,7 +321,7 @@ void LaunchController::launchInstance()
return; return;
} }
m_launcher = m_instance->createLaunchTask(m_session, m_serverToJoin); m_launcher = m_instance->createLaunchTask(m_session, m_quickPlayTarget);
if (!m_launcher) if (!m_launcher)
{ {
emitFailed(tr("Couldn't instantiate a launcher.")); emitFailed(tr("Couldn't instantiate a launcher."));

View File

@ -3,7 +3,7 @@
#include <BaseInstance.h> #include <BaseInstance.h>
#include <tools/BaseProfiler.h> #include <tools/BaseProfiler.h>
#include "minecraft/launch/MinecraftServerTarget.h" #include "minecraft/launch/QuickPlayTarget.h"
#include "minecraft/auth/MinecraftAccount.h" #include "minecraft/auth/MinecraftAccount.h"
class InstanceWindow; class InstanceWindow;
@ -40,8 +40,8 @@ public:
m_parentWidget = widget; m_parentWidget = widget;
} }
void setServerToJoin(MinecraftServerTargetPtr serverToJoin) { void setQuickPlayTarget(QuickPlayTargetPtr quickPlayTarget) {
m_serverToJoin = std::move(serverToJoin); m_quickPlayTarget = std::move(quickPlayTarget);
} }
void setAccountToUse(MinecraftAccountPtr accountToUse) { void setAccountToUse(MinecraftAccountPtr accountToUse) {
@ -77,5 +77,5 @@ private:
MinecraftAccountPtr m_accountToUse = nullptr; MinecraftAccountPtr m_accountToUse = nullptr;
AuthSessionPtr m_session; AuthSessionPtr m_session;
shared_qobject_ptr<LaunchTask> m_launcher; shared_qobject_ptr<LaunchTask> m_launcher;
MinecraftServerTargetPtr m_serverToJoin; QuickPlayTargetPtr m_quickPlayTarget;
}; };

View File

@ -27,7 +27,7 @@ public:
{ {
return instanceRoot(); return instanceRoot();
}; };
shared_qobject_ptr<LaunchTask> createLaunchTask(AuthSessionPtr, MinecraftServerTargetPtr) override shared_qobject_ptr<LaunchTask> createLaunchTask(AuthSessionPtr, QuickPlayTargetPtr) override
{ {
return nullptr; return nullptr;
} }
@ -67,7 +67,7 @@ public:
{ {
return false; return false;
} }
QStringList verboseDescription(AuthSessionPtr session, MinecraftServerTargetPtr serverToJoin) override QStringList verboseDescription(AuthSessionPtr session, QuickPlayTargetPtr quickPlayTarget) override
{ {
QStringList out; QStringList out;
out << "Null instance - placeholder."; out << "Null instance - placeholder.";

View File

@ -1,4 +1,4 @@
/* Copyright 2013-2021 MultiMC Contributors /* Copyright 2013-2023 MultiMC Contributors
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -32,7 +32,7 @@ void LookupServerAddress::setLookupAddress(const QString &lookupAddress)
m_dnsLookup->setName(QString("_minecraft._tcp.%1").arg(lookupAddress)); m_dnsLookup->setName(QString("_minecraft._tcp.%1").arg(lookupAddress));
} }
void LookupServerAddress::setOutputAddressPtr(MinecraftServerTargetPtr output) void LookupServerAddress::setOutputAddressPtr(QuickPlayTargetPtr output)
{ {
m_output = std::move(output); m_output = std::move(output);
} }

View File

@ -19,7 +19,7 @@
#include <QObjectPtr.h> #include <QObjectPtr.h>
#include <QDnsLookup> #include <QDnsLookup>
#include "minecraft/launch/MinecraftServerTarget.h" #include "minecraft/launch/QuickPlayTarget.h"
class LookupServerAddress: public LaunchStep { class LookupServerAddress: public LaunchStep {
Q_OBJECT Q_OBJECT
@ -35,7 +35,7 @@ public:
} }
void setLookupAddress(const QString &lookupAddress); void setLookupAddress(const QString &lookupAddress);
void setOutputAddressPtr(MinecraftServerTargetPtr output); void setOutputAddressPtr(QuickPlayTargetPtr output);
private slots: private slots:
void on_dnsLookupFinished(); void on_dnsLookupFinished();
@ -45,5 +45,5 @@ private:
QDnsLookup *m_dnsLookup; QDnsLookup *m_dnsLookup;
QString m_lookupAddress; QString m_lookupAddress;
MinecraftServerTargetPtr m_output; QuickPlayTargetPtr m_output;
}; };

View File

@ -122,8 +122,11 @@ MinecraftInstance::MinecraftInstance(SettingsObjectPtr globalSettings, SettingsO
m_settings->registerOverride(globalSettings->getSetting("RecordGameTime"), gameTimeOverride); m_settings->registerOverride(globalSettings->getSetting("RecordGameTime"), gameTimeOverride);
// Join server on launch, this does not have a global override // Join server on launch, this does not have a global override
m_settings->registerSetting("JoinWorldOnLaunch", false);
m_settings->registerSetting("JoinServerOnLaunch", false); m_settings->registerSetting("JoinServerOnLaunch", false);
m_settings->registerSetting("JoinServerOnLaunchAddress", ""); m_settings->registerSetting("JoinServerOnLaunchAddress", "");
m_settings->registerSetting("JoinSingleplayerWorldOnLaunch", false);
m_settings->registerSetting("JoinSingleplayerWorldOnLaunchName", "");
// DEPRECATED: Read what versions the user configuration thinks should be used // DEPRECATED: Read what versions the user configuration thinks should be used
m_settings->registerSetting({"IntendedVersion", "MinecraftVersion"}, ""); m_settings->registerSetting({"IntendedVersion", "MinecraftVersion"}, "");
@ -415,7 +418,7 @@ static QString replaceTokensIn(QString text, QMap<QString, QString> with)
} }
QStringList MinecraftInstance::processMinecraftArgs( QStringList MinecraftInstance::processMinecraftArgs(
AuthSessionPtr session, MinecraftServerTargetPtr serverToJoin) const AuthSessionPtr session, QuickPlayTargetPtr quickPlayTarget) const
{ {
auto profile = m_components->getProfile(); auto profile = m_components->getProfile();
QString args_pattern = profile->getMinecraftArguments(); QString args_pattern = profile->getMinecraftArguments();
@ -424,19 +427,24 @@ QStringList MinecraftInstance::processMinecraftArgs(
args_pattern += " --tweakClass " + tweaker; args_pattern += " --tweakClass " + tweaker;
} }
if (serverToJoin && !serverToJoin->address.isEmpty()) if (quickPlayTarget && !quickPlayTarget->address.isEmpty())
{ {
if (m_components->getComponent("net.minecraft")->getReleaseDateTime() >= g_VersionFilterData.quickPlayBeginsDate) if (m_components->getComponent("net.minecraft")->getReleaseDateTime() >= g_VersionFilterData.quickPlayBeginsDate)
{ {
args_pattern += " --quickPlayMultiplayer " + serverToJoin->address + ":" + QString::number(serverToJoin->port); args_pattern += " --quickPlayMultiplayer " + quickPlayTarget->address + ":" + QString::number(quickPlayTarget->port);
} }
else else
{ {
args_pattern += " --server " + serverToJoin->address; args_pattern += " --server " + quickPlayTarget->address;
args_pattern += " --port " + QString::number(serverToJoin->port); args_pattern += " --port " + QString::number(quickPlayTarget->port);
} }
} }
if (quickPlayTarget && !quickPlayTarget->world.isEmpty())
{
args_pattern += " --quickPlaySingleplayer \"" + quickPlayTarget->world + "\"";
}
QMap<QString, QString> token_mapping; QMap<QString, QString> token_mapping;
// yggdrasil! // yggdrasil!
if(session) { if(session) {
@ -474,7 +482,7 @@ QStringList MinecraftInstance::processMinecraftArgs(
return parts; return parts;
} }
QString MinecraftInstance::createLaunchScript(AuthSessionPtr session, MinecraftServerTargetPtr serverToJoin) QString MinecraftInstance::createLaunchScript(AuthSessionPtr session, QuickPlayTargetPtr quickPlayTarget)
{ {
QString launchScript; QString launchScript;
@ -495,17 +503,22 @@ QString MinecraftInstance::createLaunchScript(AuthSessionPtr session, MinecraftS
launchScript += "appletClass " + appletClass + "\n"; launchScript += "appletClass " + appletClass + "\n";
} }
if (serverToJoin && !serverToJoin->address.isEmpty()) if (quickPlayTarget && !quickPlayTarget->address.isEmpty())
{ {
launchScript += "useQuickPlay " + QString::number(m_components->getComponent("net.minecraft")->getReleaseDateTime() >= g_VersionFilterData.quickPlayBeginsDate) + "\n"; launchScript += "useQuickPlay " + QString::number(m_components->getComponent("net.minecraft")->getReleaseDateTime() >= g_VersionFilterData.quickPlayBeginsDate) + "\n";
launchScript += "serverAddress " + serverToJoin->address + "\n"; launchScript += "serverAddress " + quickPlayTarget->address + "\n";
launchScript += "serverPort " + QString::number(serverToJoin->port) + "\n"; launchScript += "serverPort " + QString::number(quickPlayTarget->port) + "\n";
}
if (quickPlayTarget && !quickPlayTarget->world.isEmpty())
{
launchScript += "joinWorld " + quickPlayTarget->world + "\n";
} }
// generic minecraft params // generic minecraft params
for (auto param : processMinecraftArgs( for (auto param : processMinecraftArgs(
session, session,
nullptr /* When using a launch script, the server parameters are handled by it*/ nullptr /* When using a launch script, the server and world parameters are handled by it*/
)) ))
{ {
launchScript += "param " + param + "\n"; launchScript += "param " + param + "\n";
@ -558,7 +571,7 @@ QString MinecraftInstance::createLaunchScript(AuthSessionPtr session, MinecraftS
return launchScript; return launchScript;
} }
QStringList MinecraftInstance::verboseDescription(AuthSessionPtr session, MinecraftServerTargetPtr serverToJoin) QStringList MinecraftInstance::verboseDescription(AuthSessionPtr session, QuickPlayTargetPtr quickPlayTarget)
{ {
QStringList out; QStringList out;
out << "Main Class:" << " " + getMainClass() << ""; out << "Main Class:" << " " + getMainClass() << "";
@ -673,7 +686,7 @@ QStringList MinecraftInstance::verboseDescription(AuthSessionPtr session, Minecr
out << ""; out << "";
} }
auto params = processMinecraftArgs(nullptr, serverToJoin); auto params = processMinecraftArgs(nullptr, quickPlayTarget);
out << "Params:"; out << "Params:";
out << " " + params.join(' '); out << " " + params.join(' ');
out << ""; out << "";
@ -834,7 +847,7 @@ Task::Ptr MinecraftInstance::createUpdateTask(Net::Mode mode)
return nullptr; return nullptr;
} }
shared_qobject_ptr<LaunchTask> MinecraftInstance::createLaunchTask(AuthSessionPtr session, MinecraftServerTargetPtr serverToJoin) shared_qobject_ptr<LaunchTask> MinecraftInstance::createLaunchTask(AuthSessionPtr session, QuickPlayTargetPtr quickPlayTarget)
{ {
// FIXME: get rid of shared_from_this ... // FIXME: get rid of shared_from_this ...
auto process = LaunchTask::create(std::dynamic_pointer_cast<MinecraftInstance>(shared_from_this())); auto process = LaunchTask::create(std::dynamic_pointer_cast<MinecraftInstance>(shared_from_this()));
@ -866,18 +879,26 @@ shared_qobject_ptr<LaunchTask> MinecraftInstance::createLaunchTask(AuthSessionPt
process->appendStep(new CreateGameFolders(pptr)); process->appendStep(new CreateGameFolders(pptr));
} }
if (!serverToJoin && m_settings->get("JoinServerOnLaunch").toBool()) if (!quickPlayTarget && m_settings->get("JoinWorldOnLaunch").toBool())
{
if (m_settings->get("JoinServerOnLaunch").toBool())
{ {
QString fullAddress = m_settings->get("JoinServerOnLaunchAddress").toString(); QString fullAddress = m_settings->get("JoinServerOnLaunchAddress").toString();
serverToJoin.reset(new MinecraftServerTarget(MinecraftServerTarget::parse(fullAddress))); quickPlayTarget.reset(new QuickPlayTarget(QuickPlayTarget::parseMultiplayer(fullAddress)));
}
else if (m_settings->get("JoinSingleplayerWorldOnLaunch").toBool())
{
QString worldName = m_settings->get("JoinSingleplayerWorldOnLaunchName").toString();
quickPlayTarget.reset(new QuickPlayTarget(QuickPlayTarget::parseSingleplayer(worldName)));
}
} }
if(serverToJoin && serverToJoin->port == 25565) if(quickPlayTarget && quickPlayTarget->port == 25565)
{ {
// Resolve server address to join on launch // Resolve server address to join on launch
auto *step = new LookupServerAddress(pptr); auto *step = new LookupServerAddress(pptr);
step->setLookupAddress(serverToJoin->address); step->setLookupAddress(quickPlayTarget->address);
step->setOutputAddressPtr(serverToJoin); step->setOutputAddressPtr(quickPlayTarget);
process->appendStep(step); process->appendStep(step);
} }
@ -914,7 +935,7 @@ shared_qobject_ptr<LaunchTask> MinecraftInstance::createLaunchTask(AuthSessionPt
// print some instance info here... // print some instance info here...
{ {
process->appendStep(new PrintInstanceInfo(pptr, session, serverToJoin)); process->appendStep(new PrintInstanceInfo(pptr, session, quickPlayTarget));
} }
// extract native jars if needed // extract native jars if needed
@ -940,7 +961,7 @@ shared_qobject_ptr<LaunchTask> MinecraftInstance::createLaunchTask(AuthSessionPt
auto step = new LauncherPartLaunch(pptr); auto step = new LauncherPartLaunch(pptr);
step->setWorkingDirectory(gameRoot()); step->setWorkingDirectory(gameRoot());
step->setAuthSession(session); step->setAuthSession(session);
step->setServerToJoin(serverToJoin); step->setQuickPlayTarget(quickPlayTarget);
process->appendStep(step); process->appendStep(step);
} }
else if (method == "DirectJava") else if (method == "DirectJava")
@ -948,7 +969,7 @@ shared_qobject_ptr<LaunchTask> MinecraftInstance::createLaunchTask(AuthSessionPt
auto step = new DirectJavaLaunch(pptr); auto step = new DirectJavaLaunch(pptr);
step->setWorkingDirectory(gameRoot()); step->setWorkingDirectory(gameRoot());
step->setAuthSession(session); step->setAuthSession(session);
step->setServerToJoin(serverToJoin); step->setQuickPlayTarget(quickPlayTarget);
process->appendStep(step); process->appendStep(step);
} }
} }

View File

@ -4,7 +4,7 @@
#include "minecraft/mod/Mod.h" #include "minecraft/mod/Mod.h"
#include <QProcess> #include <QProcess>
#include <QDir> #include <QDir>
#include "minecraft/launch/MinecraftServerTarget.h" #include "minecraft/launch/QuickPlayTarget.h"
class ModFolderModel; class ModFolderModel;
class WorldList; class WorldList;
@ -78,11 +78,11 @@ public:
////// Launch stuff ////// ////// Launch stuff //////
Task::Ptr createUpdateTask(Net::Mode mode) override; Task::Ptr createUpdateTask(Net::Mode mode) override;
shared_qobject_ptr<LaunchTask> createLaunchTask(AuthSessionPtr account, MinecraftServerTargetPtr serverToJoin) override; shared_qobject_ptr<LaunchTask> createLaunchTask(AuthSessionPtr account, QuickPlayTargetPtr quickPlayTarget) override;
QStringList extraArguments() const override; QStringList extraArguments() const override;
QStringList verboseDescription(AuthSessionPtr session, MinecraftServerTargetPtr serverToJoin) override; QStringList verboseDescription(AuthSessionPtr session, QuickPlayTargetPtr quickPlayTarget) override;
QList<Mod> getJarMods() const; QList<Mod> getJarMods() const;
QString createLaunchScript(AuthSessionPtr session, MinecraftServerTargetPtr serverToJoin); QString createLaunchScript(AuthSessionPtr session, QuickPlayTargetPtr quickPlayTarget);
/// get arguments passed to java /// get arguments passed to java
QStringList javaArguments() const; QStringList javaArguments() const;
@ -109,7 +109,7 @@ public:
virtual QString getMainClass() const; virtual QString getMainClass() const;
// FIXME: remove // FIXME: remove
virtual QStringList processMinecraftArgs(AuthSessionPtr account, MinecraftServerTargetPtr serverToJoin) const; virtual QStringList processMinecraftArgs(AuthSessionPtr account, QuickPlayTargetPtr quickPlayTarget) const;
virtual JavaVersion getJavaVersion() const; virtual JavaVersion getJavaVersion() const;

View File

@ -1,4 +1,4 @@
/* Copyright 2013-2021 MultiMC Contributors /* Copyright 2013-2023 MultiMC Contributors
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -55,7 +55,7 @@ void DirectJavaLaunch::executeTask()
// make detachable - this will keep the process running even if the object is destroyed // make detachable - this will keep the process running even if the object is destroyed
m_process.setDetachable(true); m_process.setDetachable(true);
auto mcArgs = minecraftInstance->processMinecraftArgs(m_session, m_serverToJoin); auto mcArgs = minecraftInstance->processMinecraftArgs(m_session, m_quickPlayTarget);
args.append(mcArgs); args.append(mcArgs);
QString wrapperCommandStr = instance->getWrapperCommand().trimmed(); QString wrapperCommandStr = instance->getWrapperCommand().trimmed();

View File

@ -1,4 +1,4 @@
/* Copyright 2013-2021 MultiMC Contributors /* Copyright 2013-2023 MultiMC Contributors
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -19,7 +19,7 @@
#include <LoggedProcess.h> #include <LoggedProcess.h>
#include <minecraft/auth/AuthSession.h> #include <minecraft/auth/AuthSession.h>
#include "MinecraftServerTarget.h" #include "QuickPlayTarget.h"
class DirectJavaLaunch: public LaunchStep class DirectJavaLaunch: public LaunchStep
{ {
@ -41,9 +41,9 @@ public:
m_session = session; m_session = session;
} }
void setServerToJoin(MinecraftServerTargetPtr serverToJoin) void setQuickPlayTarget(QuickPlayTargetPtr quickPlayTarget)
{ {
m_serverToJoin = std::move(serverToJoin); m_quickPlayTarget = std::move(quickPlayTarget);
} }
private slots: private slots:
@ -53,6 +53,6 @@ private:
LoggedProcess m_process; LoggedProcess m_process;
QString m_command; QString m_command;
AuthSessionPtr m_session; AuthSessionPtr m_session;
MinecraftServerTargetPtr m_serverToJoin; QuickPlayTargetPtr m_quickPlayTarget;
}; };

View File

@ -1,4 +1,4 @@
/* Copyright 2013-2021 MultiMC Contributors /* Copyright 2013-2023 MultiMC Contributors
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -60,7 +60,7 @@ void LauncherPartLaunch::executeTask()
auto instance = m_parent->instance(); auto instance = m_parent->instance();
std::shared_ptr<MinecraftInstance> minecraftInstance = std::dynamic_pointer_cast<MinecraftInstance>(instance); std::shared_ptr<MinecraftInstance> minecraftInstance = std::dynamic_pointer_cast<MinecraftInstance>(instance);
m_launchScript = minecraftInstance->createLaunchScript(m_session, m_serverToJoin); m_launchScript = minecraftInstance->createLaunchScript(m_session, m_quickPlayTarget);
QStringList args = minecraftInstance->javaArguments(); QStringList args = minecraftInstance->javaArguments();
QString allArgs = args.join(", "); QString allArgs = args.join(", ");
emit logLine("Java Arguments:\n[" + m_parent->censorPrivateInfo(allArgs) + "]\n\n", MessageLevel::Launcher); emit logLine("Java Arguments:\n[" + m_parent->censorPrivateInfo(allArgs) + "]\n\n", MessageLevel::Launcher);

View File

@ -1,4 +1,4 @@
/* Copyright 2013-2021 MultiMC Contributors /* Copyright 2013-2023 MultiMC Contributors
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -19,7 +19,7 @@
#include <LoggedProcess.h> #include <LoggedProcess.h>
#include <minecraft/auth/AuthSession.h> #include <minecraft/auth/AuthSession.h>
#include "MinecraftServerTarget.h" #include "QuickPlayTarget.h"
class LauncherPartLaunch: public LaunchStep class LauncherPartLaunch: public LaunchStep
{ {
@ -41,9 +41,9 @@ public:
m_session = session; m_session = session;
} }
void setServerToJoin(MinecraftServerTargetPtr serverToJoin) void setQuickPlayTarget(QuickPlayTargetPtr quickPlayTarget)
{ {
m_serverToJoin = std::move(serverToJoin); m_quickPlayTarget = std::move(quickPlayTarget);
} }
private slots: private slots:
@ -54,7 +54,7 @@ private:
QString m_command; QString m_command;
AuthSessionPtr m_session; AuthSessionPtr m_session;
QString m_launchScript; QString m_launchScript;
MinecraftServerTargetPtr m_serverToJoin; QuickPlayTargetPtr m_quickPlayTarget;
bool mayProceed = false; bool mayProceed = false;
}; };

View File

@ -1,4 +1,4 @@
/* Copyright 2013-2021 MultiMC Contributors /* Copyright 2013-2023 MultiMC Contributors
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -142,6 +142,6 @@ void PrintInstanceInfo::executeTask()
#endif #endif
logLines(log, MessageLevel::Launcher); logLines(log, MessageLevel::Launcher);
logLines(instance->verboseDescription(m_session, m_serverToJoin), MessageLevel::Launcher); logLines(instance->verboseDescription(m_session, m_quickPlayTarget), MessageLevel::Launcher);
emitSucceeded(); emitSucceeded();
} }

View File

@ -1,4 +1,4 @@
/* Copyright 2013-2021 MultiMC Contributors /* Copyright 2013-2023 MultiMC Contributors
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -18,15 +18,15 @@
#include <launch/LaunchStep.h> #include <launch/LaunchStep.h>
#include <memory> #include <memory>
#include "minecraft/auth/AuthSession.h" #include "minecraft/auth/AuthSession.h"
#include "minecraft/launch/MinecraftServerTarget.h" #include "minecraft/launch/QuickPlayTarget.h"
// FIXME: temporary wrapper for existing task. // FIXME: temporary wrapper for existing task.
class PrintInstanceInfo: public LaunchStep class PrintInstanceInfo: public LaunchStep
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit PrintInstanceInfo(LaunchTask *parent, AuthSessionPtr session, MinecraftServerTargetPtr serverToJoin) : explicit PrintInstanceInfo(LaunchTask *parent, AuthSessionPtr session, QuickPlayTargetPtr quickPlayTarget) :
LaunchStep(parent), m_session(session), m_serverToJoin(serverToJoin) {}; LaunchStep(parent), m_session(session), m_quickPlayTarget(quickPlayTarget) {};
virtual ~PrintInstanceInfo(){}; virtual ~PrintInstanceInfo(){};
virtual void executeTask(); virtual void executeTask();
@ -36,6 +36,6 @@ public:
} }
private: private:
AuthSessionPtr m_session; AuthSessionPtr m_session;
MinecraftServerTargetPtr m_serverToJoin; QuickPlayTargetPtr m_quickPlayTarget;
}; };

View File

@ -1,4 +1,4 @@
/* Copyright 2013-2021 MultiMC Contributors /* Copyright 2013-2023 MultiMC Contributors
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -13,12 +13,12 @@
* limitations under the License. * limitations under the License.
*/ */
#include "MinecraftServerTarget.h" #include "QuickPlayTarget.h"
#include <QStringList> #include <QStringList>
// FIXME: the way this is written, it can't ever do any sort of validation and can accept total junk // FIXME: the way this is written, it can't ever do any sort of validation and can accept total junk
MinecraftServerTarget MinecraftServerTarget::parse(const QString &fullAddress) { QuickPlayTarget QuickPlayTarget::parseMultiplayer(const QString &fullAddress) {
QStringList split = fullAddress.split(":"); QStringList split = fullAddress.split(":");
// The logic below replicates the exact logic minecraft uses for parsing server addresses. // The logic below replicates the exact logic minecraft uses for parsing server addresses.
@ -63,5 +63,12 @@ MinecraftServerTarget MinecraftServerTarget::parse(const QString &fullAddress) {
} }
} }
return MinecraftServerTarget { realAddress, realPort }; return QuickPlayTarget { realAddress, realPort };
}
QuickPlayTarget QuickPlayTarget::parseSingleplayer(const QString &worldName)
{
QuickPlayTarget target;
target.world = worldName;
return target;
} }

View File

@ -1,4 +1,4 @@
/* Copyright 2013-2021 MultiMC Contributors /* Copyright 2013-2023 MultiMC Contributors
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -19,11 +19,16 @@
#include <QString> #include <QString>
struct MinecraftServerTarget { struct QuickPlayTarget {
// Multiplayer
QString address; QString address;
quint16 port; quint16 port;
static MinecraftServerTarget parse(const QString &fullAddress); // Singleplayer
QString world;
static QuickPlayTarget parseMultiplayer(const QString &fullAddress);
static QuickPlayTarget parseSingleplayer(const QString &worldName);
}; };
typedef std::shared_ptr<MinecraftServerTarget> MinecraftServerTargetPtr; typedef std::shared_ptr<QuickPlayTarget> QuickPlayTargetPtr;

View File

@ -1,4 +1,4 @@
/* Copyright 2013-2021 MultiMC Contributors /* Copyright 2013-2023 MultiMC Contributors
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -225,7 +225,7 @@ QString LegacyInstance::getStatusbarDescription()
return tr("Instance from previous versions."); return tr("Instance from previous versions.");
} }
QStringList LegacyInstance::verboseDescription(AuthSessionPtr session, MinecraftServerTargetPtr serverToJoin) QStringList LegacyInstance::verboseDescription(AuthSessionPtr session, QuickPlayTargetPtr quickPlayTarget)
{ {
QStringList out; QStringList out;

View File

@ -1,4 +1,4 @@
/* Copyright 2013-2021 MultiMC Contributors /* Copyright 2013-2023 MultiMC Contributors
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -112,7 +112,7 @@ public:
return false; return false;
} }
shared_qobject_ptr<LaunchTask> createLaunchTask( shared_qobject_ptr<LaunchTask> createLaunchTask(
AuthSessionPtr account, MinecraftServerTargetPtr serverToJoin) override AuthSessionPtr account, QuickPlayTargetPtr quickPlayTarget) override
{ {
return nullptr; return nullptr;
} }
@ -126,7 +126,7 @@ public:
} }
QString getStatusbarDescription() override; QString getStatusbarDescription() override;
QStringList verboseDescription(AuthSessionPtr session, MinecraftServerTargetPtr serverToJoin) override; QStringList verboseDescription(AuthSessionPtr session, QuickPlayTargetPtr quickPlayTarget) override;
QProcessEnvironment createEnvironment() override QProcessEnvironment createEnvironment() override
{ {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2022 arthomnix * Copyright 2022-2023 arthomnix
* *
* This source is subject to the Microsoft Public License (MS-PL). * This source is subject to the Microsoft Public License (MS-PL).
* Please see the COPYING.md file for more information. * Please see the COPYING.md file for more information.
@ -13,6 +13,8 @@
#include "Application.h" #include "Application.h"
#include "minecraft/auth/AccountList.h" #include "minecraft/auth/AccountList.h"
#include "minecraft/MinecraftInstance.h" #include "minecraft/MinecraftInstance.h"
#include "minecraft/WorldList.h"
#include "minecraft/VersionFilterData.h"
#include "minecraft/PackProfile.h" #include "minecraft/PackProfile.h"
#include "icons/IconList.h" #include "icons/IconList.h"
@ -43,6 +45,23 @@ CreateShortcutDialog::CreateShortcutDialog(QWidget *parent, InstancePtr instance
// TODO: check if version is affected by crashing when joining servers on launch, ideally in meta // TODO: check if version is affected by crashing when joining servers on launch, ideally in meta
auto mcInstance = std::dynamic_pointer_cast<MinecraftInstance>(instance);
mcInstance->getPackProfile()->reload(Net::Mode::Offline);
if (mcInstance && mcInstance->getPackProfile()->getComponent("net.minecraft")->getReleaseDateTime() >= g_VersionFilterData.quickPlayBeginsDate)
{
mcInstance->worldList()->update();
for (const auto &world : mcInstance->worldList()->allWorlds())
{
ui->joinSingleplayer->addItem(world.folderName());
}
}
else
{
ui->joinServerRadioButton->setChecked(true);
ui->joinSingleplayerRadioButton->setVisible(false);
ui->joinSingleplayer->setVisible(false);
}
// Macs don't have any concept of a desktop shortcut, so force-enable the option to generate a shell script instead // Macs don't have any concept of a desktop shortcut, so force-enable the option to generate a shell script instead
#if defined(Q_OS_UNIX) && !defined(Q_OS_LINUX) #if defined(Q_OS_UNIX) && !defined(Q_OS_LINUX)
ui->createScriptCheckBox->setEnabled(false); ui->createScriptCheckBox->setEnabled(false);
@ -90,16 +109,16 @@ void CreateShortcutDialog::accept()
void CreateShortcutDialog::updateDialogState() void CreateShortcutDialog::updateDialogState()
{ {
ui->buttonBox->button(QDialogButtonBox::StandardButton::Ok)->setEnabled( ui->buttonBox->button(QDialogButtonBox::StandardButton::Ok)->setEnabled(
!ui->shortcutPath->text().isEmpty() !ui->shortcutPath->text().isEmpty()
&& (!ui->joinServerCheckBox->isChecked() || !ui->joinServer->text().isEmpty()) && (!ui->joinWorldCheckBox->isChecked() || ui->joinServerRadioButton->isChecked() || ui->joinSingleplayerRadioButton->isChecked())
&& (!ui->joinServerRadioButton->isChecked() || !ui->joinServer->text().isEmpty())
&& (!ui->joinSingleplayerRadioButton->isChecked() || !ui->joinSingleplayer->currentText().isEmpty())
&& (!ui->offlineUsernameCheckBox->isChecked() || !ui->offlineUsername->text().isEmpty()) && (!ui->offlineUsernameCheckBox->isChecked() || !ui->offlineUsername->text().isEmpty())
&& (!ui->useProfileCheckBox->isChecked() || !ui->profileComboBox->currentText().isEmpty()) && (!ui->useProfileCheckBox->isChecked() || !ui->profileComboBox->currentText().isEmpty())
); );
ui->joinServer->setEnabled(ui->joinServerCheckBox->isChecked()); ui->joinServer->setEnabled(ui->joinWorldCheckBox->isChecked() && ui->joinServerRadioButton->isChecked());
ui->profileComboBox->setEnabled(ui->useProfileCheckBox->isChecked()); ui->joinSingleplayer->setEnabled(ui->joinWorldCheckBox->isChecked() && ui->joinSingleplayerRadioButton->isChecked());
ui->offlineUsernameCheckBox->setEnabled(ui->launchOfflineCheckBox->isChecked());
ui->offlineUsername->setEnabled(ui->launchOfflineCheckBox->isChecked() && ui->offlineUsernameCheckBox->isChecked()); ui->offlineUsername->setEnabled(ui->launchOfflineCheckBox->isChecked() && ui->offlineUsernameCheckBox->isChecked());
if (!ui->launchOfflineCheckBox->isChecked()) if (!ui->launchOfflineCheckBox->isChecked())
{ {
@ -117,7 +136,8 @@ QString CreateShortcutDialog::getLaunchArgs(bool escapeQuotesTwice)
{ {
return " -d \"" + QDir::toNativeSeparators(QDir::currentPath()).replace('"', escapeQuotesTwice ? "\\\\\"" : "\\\"") + "\"" return " -d \"" + QDir::toNativeSeparators(QDir::currentPath()).replace('"', escapeQuotesTwice ? "\\\\\"" : "\\\"") + "\""
+ " -l \"" + m_instance->id() + "\"" + " -l \"" + m_instance->id() + "\""
+ (ui->joinServerCheckBox->isChecked() ? " -s \"" + ui->joinServer->text() + "\"" : "") + (ui->joinServerRadioButton->isChecked() ? " -s \"" + ui->joinServer->text() + "\"" : "")
+ (ui->joinSingleplayerRadioButton->isChecked() ? " -w \"" + ui->joinSingleplayer->currentText() + "\"" : "")
+ (ui->useProfileCheckBox->isChecked() ? " -a \"" + ui->profileComboBox->currentText() + "\"" : "") + (ui->useProfileCheckBox->isChecked() ? " -a \"" + ui->profileComboBox->currentText() + "\"" : "")
+ (ui->launchOfflineCheckBox->isChecked() ? " -o" : "") + (ui->launchOfflineCheckBox->isChecked() ? " -o" : "")
+ (ui->offlineUsernameCheckBox->isChecked() ? " -n \"" + ui->offlineUsername->text() + "\"" : ""); + (ui->offlineUsernameCheckBox->isChecked() ? " -n \"" + ui->offlineUsername->text() + "\"" : "");

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!-- <!--
Copyright 2022 arthomnix Copyright 2022-2023 arthomnix
This source is subject to the Microsoft Public License (MS-PL). This source is subject to the Microsoft Public License (MS-PL).
Please see the COPYING.md file for more information. Please see the COPYING.md file for more information.
--> -->
@ -12,7 +12,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>796</width> <width>796</width>
<height>232</height> <height>330</height>
</rect> </rect>
</property> </property>
<property name="minimumSize"> <property name="minimumSize">
@ -30,17 +30,82 @@
<property name="sizeConstraint"> <property name="sizeConstraint">
<enum>QLayout::SetDefaultConstraint</enum> <enum>QLayout::SetDefaultConstraint</enum>
</property> </property>
<item row="3" column="0"> <item row="0" column="0">
<widget class="QLabel" name="shortcutPathLabel">
<property name="text">
<string>Shortcut path:</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QCheckBox" name="useProfileCheckBox">
<property name="text">
<string>Use specific profile:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QComboBox" name="joinSingleplayer">
<property name="enabled">
<bool>false</bool>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QCheckBox" name="launchOfflineCheckBox"> <widget class="QCheckBox" name="launchOfflineCheckBox">
<property name="text"> <property name="text">
<string>Launch in offline mode</string> <string>Launch in offline mode</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="0" column="0"> <item row="6" column="1">
<widget class="QLabel" name="shortcutPathLabel"> <widget class="QLineEdit" name="offlineUsername">
<property name="enabled">
<bool>false</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="joinWorldCheckBox">
<property name="text"> <property name="text">
<string>Shortcut path:</string> <string>Join world on launch:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="joinServer">
<property name="enabled">
<bool>false</bool>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QComboBox" name="profileComboBox">
<property name="enabled">
<bool>false</bool>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="shortcutPath"/>
</item>
<item row="6" column="0">
<widget class="QCheckBox" name="offlineUsernameCheckBox">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Set offline mode username:</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QRadioButton" name="joinSingleplayerRadioButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Singleplayer world:</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -51,39 +116,16 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="0" column="1">
<widget class="QLineEdit" name="shortcutPath"/>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="profileComboBox"/>
</item>
<item row="4" column="1">
<widget class="QLineEdit" name="offlineUsername"/>
</item>
<item row="4" column="0">
<widget class="QCheckBox" name="offlineUsernameCheckBox">
<property name="text">
<string>Set offline mode username:</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="joinServerCheckBox">
<property name="text">
<string>Join server on launch:</string>
</property>
</widget>
</item>
<item row="2" column="0"> <item row="2" column="0">
<widget class="QCheckBox" name="useProfileCheckBox"> <widget class="QRadioButton" name="joinServerRadioButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text"> <property name="text">
<string>Use specific profile:</string> <string>Server address:</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="1">
<widget class="QLineEdit" name="joinServer"/>
</item>
</layout> </layout>
</item> </item>
<item> <item>
@ -173,18 +215,18 @@
</hints> </hints>
</connection> </connection>
<connection> <connection>
<sender>joinServerCheckBox</sender> <sender>joinWorldCheckBox</sender>
<signal>stateChanged(int)</signal> <signal>toggled(bool)</signal>
<receiver>CreateShortcutDialog</receiver> <receiver>joinServerRadioButton</receiver>
<slot>updateDialogState()</slot> <slot>setEnabled(bool)</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>122</x> <x>122</x>
<y>61</y> <y>61</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>397</x> <x>140</x>
<y>114</y> <y>93</y>
</hint> </hint>
</hints> </hints>
</connection> </connection>
@ -284,5 +326,136 @@
</hint> </hint>
</hints> </hints>
</connection> </connection>
<connection>
<sender>joinWorldCheckBox</sender>
<signal>toggled(bool)</signal>
<receiver>joinSingleplayerRadioButton</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>140</x>
<y>59</y>
</hint>
<hint type="destinationlabel">
<x>140</x>
<y>132</y>
</hint>
</hints>
</connection>
<connection>
<sender>joinServerRadioButton</sender>
<signal>toggled(bool)</signal>
<receiver>joinServer</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>140</x>
<y>93</y>
</hint>
<hint type="destinationlabel">
<x>489</x>
<y>93</y>
</hint>
</hints>
</connection>
<connection>
<sender>joinSingleplayerRadioButton</sender>
<signal>toggled(bool)</signal>
<receiver>joinSingleplayer</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>140</x>
<y>132</y>
</hint>
<hint type="destinationlabel">
<x>489</x>
<y>132</y>
</hint>
</hints>
</connection>
<connection>
<sender>useProfileCheckBox</sender>
<signal>toggled(bool)</signal>
<receiver>profileComboBox</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>140</x>
<y>171</y>
</hint>
<hint type="destinationlabel">
<x>489</x>
<y>171</y>
</hint>
</hints>
</connection>
<connection>
<sender>launchOfflineCheckBox</sender>
<signal>toggled(bool)</signal>
<receiver>offlineUsernameCheckBox</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>140</x>
<y>205</y>
</hint>
<hint type="destinationlabel">
<x>140</x>
<y>239</y>
</hint>
</hints>
</connection>
<connection>
<sender>joinSingleplayer</sender>
<signal>currentTextChanged(QString)</signal>
<receiver>CreateShortcutDialog</receiver>
<slot>updateDialogState()</slot>
<hints>
<hint type="sourcelabel">
<x>489</x>
<y>132</y>
</hint>
<hint type="destinationlabel">
<x>397</x>
<y>164</y>
</hint>
</hints>
</connection>
<connection>
<sender>joinServerRadioButton</sender>
<signal>toggled(bool)</signal>
<receiver>CreateShortcutDialog</receiver>
<slot>updateDialogState()</slot>
<hints>
<hint type="sourcelabel">
<x>140</x>
<y>93</y>
</hint>
<hint type="destinationlabel">
<x>397</x>
<y>164</y>
</hint>
</hints>
</connection>
<connection>
<sender>joinSingleplayerRadioButton</sender>
<signal>toggled(bool)</signal>
<receiver>CreateShortcutDialog</receiver>
<slot>updateDialogState()</slot>
<hints>
<hint type="sourcelabel">
<x>140</x>
<y>132</y>
</hint>
<hint type="destinationlabel">
<x>397</x>
<y>164</y>
</hint>
</hints>
</connection>
</connections> </connections>
<slots>
<slot>updateDialogState()</slot>
</slots>
</ui> </ui>

View File

@ -16,6 +16,10 @@
#include "java/JavaInstallList.h" #include "java/JavaInstallList.h"
#include "FileSystem.h" #include "FileSystem.h"
#include "minecraft/MinecraftInstance.h"
#include "minecraft/PackProfile.h"
#include "minecraft/VersionFilterData.h"
#include "minecraft/WorldList.h"
InstanceSettingsPage::InstanceSettingsPage(BaseInstance *inst, QWidget *parent) InstanceSettingsPage::InstanceSettingsPage(BaseInstance *inst, QWidget *parent)
: QWidget(parent), ui(new Ui::InstanceSettingsPage), m_instance(inst) : QWidget(parent), ui(new Ui::InstanceSettingsPage), m_instance(inst)
@ -27,6 +31,23 @@ InstanceSettingsPage::InstanceSettingsPage(BaseInstance *inst, QWidget *parent)
connect(ui->openGlobalJavaSettingsButton, &QCommandLinkButton::clicked, this, &InstanceSettingsPage::globalSettingsButtonClicked); connect(ui->openGlobalJavaSettingsButton, &QCommandLinkButton::clicked, this, &InstanceSettingsPage::globalSettingsButtonClicked);
connect(APPLICATION, &Application::globalSettingsAboutToOpen, this, &InstanceSettingsPage::applySettings); connect(APPLICATION, &Application::globalSettingsAboutToOpen, this, &InstanceSettingsPage::applySettings);
connect(APPLICATION, &Application::globalSettingsClosed, this, &InstanceSettingsPage::loadSettings); connect(APPLICATION, &Application::globalSettingsClosed, this, &InstanceSettingsPage::loadSettings);
auto *mcInst = dynamic_cast<MinecraftInstance *>(inst);
if (mcInst && mcInst->getPackProfile()->getComponent("net.minecraft")->getReleaseDateTime() >= g_VersionFilterData.quickPlayBeginsDate)
{
mcInst->worldList()->update();
for (const auto &world : mcInst->worldList()->allWorlds())
{
ui->worldsComboBox->addItem(world.folderName());
}
}
else
{
ui->worldRadioButton->setVisible(false);
ui->worldsComboBox->setVisible(false);
ui->serverAddressRadioButton->setChecked(true);
}
loadSettings(); loadSettings();
} }
@ -195,8 +216,12 @@ void InstanceSettingsPage::applySettings()
} }
// Join server on launch // Join server on launch
bool joinServerOnLaunch = ui->serverJoinGroupBox->isChecked(); bool joinWorldOnLaunch = ui->quickPlayGroupBox->isChecked();
m_settings->set("JoinWorldOnLaunch", joinWorldOnLaunch);
bool joinServerOnLaunch = ui->serverAddressRadioButton->isChecked();
m_settings->set("JoinServerOnLaunch", joinServerOnLaunch); m_settings->set("JoinServerOnLaunch", joinServerOnLaunch);
if (joinServerOnLaunch) if (joinServerOnLaunch)
{ {
m_settings->set("JoinServerOnLaunchAddress", ui->serverJoinAddress->text()); m_settings->set("JoinServerOnLaunchAddress", ui->serverJoinAddress->text());
@ -205,6 +230,18 @@ void InstanceSettingsPage::applySettings()
{ {
m_settings->reset("JoinServerOnLaunchAddress"); m_settings->reset("JoinServerOnLaunchAddress");
} }
bool joinSingleplayerWorldOnLaunch = ui->worldRadioButton->isChecked();
m_settings->set("JoinSingleplayerWorldOnLaunch", joinSingleplayerWorldOnLaunch);
if (joinSingleplayerWorldOnLaunch)
{
m_settings->set("JoinSingleplayerWorldOnLaunchName", ui->worldsComboBox->currentText());
}
else
{
m_settings->reset("JoinSingleplayerWorldOnLaunchName");
}
} }
void InstanceSettingsPage::loadSettings() void InstanceSettingsPage::loadSettings()
@ -272,8 +309,23 @@ void InstanceSettingsPage::loadSettings()
ui->showGameTime->setChecked(m_settings->get("ShowGameTime").toBool()); ui->showGameTime->setChecked(m_settings->get("ShowGameTime").toBool());
ui->recordGameTime->setChecked(m_settings->get("RecordGameTime").toBool()); ui->recordGameTime->setChecked(m_settings->get("RecordGameTime").toBool());
ui->serverJoinGroupBox->setChecked(m_settings->get("JoinServerOnLaunch").toBool()); if (!m_settings->contains("JoinWorldOnLaunch"))
{
ui->quickPlayGroupBox->setChecked(m_settings->get("JoinServerOnLaunch").toBool());
ui->serverAddressRadioButton->setChecked(m_settings->get("JoinServerOnLaunch").toBool());
ui->worldRadioButton->setChecked(false);
}
else
{
ui->quickPlayGroupBox->setChecked(m_settings->get("JoinWorldOnLaunch").toBool());
ui->serverAddressRadioButton->setChecked(m_settings->get("JoinServerOnLaunch").toBool());
ui->serverJoinAddress->setEnabled(m_settings->get("JoinServerOnLaunch").toBool());
ui->serverJoinAddress->setText(m_settings->get("JoinServerOnLaunchAddress").toString()); ui->serverJoinAddress->setText(m_settings->get("JoinServerOnLaunchAddress").toString());
ui->worldRadioButton->setChecked(m_settings->get("JoinSingleplayerWorldOnLaunch").toBool());
ui->worldsComboBox->setEnabled(m_settings->get("JoinSingleplayerWorldOnLaunch").toBool());
ui->worldsComboBox->setCurrentText(m_settings->get("JoinSingleplayerWorldOnLaunchName").toString());
}
} }
void InstanceSettingsPage::on_javaDetectBtn_clicked() void InstanceSettingsPage::on_javaDetectBtn_clicked()
@ -334,6 +386,16 @@ void InstanceSettingsPage::on_javaTestBtn_clicked()
checker->run(); checker->run();
} }
void InstanceSettingsPage::on_serverAddressRadioButton_toggled(bool checked)
{
ui->serverJoinAddress->setEnabled(checked);
}
void InstanceSettingsPage::on_worldRadioButton_toggled(bool checked)
{
ui->worldsComboBox->setEnabled(checked);
}
void InstanceSettingsPage::checkerFinished() void InstanceSettingsPage::checkerFinished()
{ {
checker.reset(); checker.reset();

View File

@ -1,4 +1,4 @@
/* Copyright 2013-2021 MultiMC Contributors /* Copyright 2013-2023 MultiMC Contributors
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -22,6 +22,7 @@
#include <QObjectPtr.h> #include <QObjectPtr.h>
#include "ui/pages/BasePage.h" #include "ui/pages/BasePage.h"
#include "JavaCommon.h" #include "JavaCommon.h"
#include "minecraft/WorldList.h"
#include "Application.h" #include "Application.h"
class JavaChecker; class JavaChecker;
@ -60,6 +61,8 @@ private slots:
void on_javaDetectBtn_clicked(); void on_javaDetectBtn_clicked();
void on_javaTestBtn_clicked(); void on_javaTestBtn_clicked();
void on_javaBrowseBtn_clicked(); void on_javaBrowseBtn_clicked();
void on_serverAddressRadioButton_toggled(bool checked);
void on_worldRadioButton_toggled(bool checked);
void applySettings(); void applySettings();
void loadSettings(); void loadSettings();

View File

@ -454,9 +454,9 @@
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QGroupBox" name="serverJoinGroupBox"> <widget class="QGroupBox" name="quickPlayGroupBox">
<property name="title"> <property name="title">
<string>Set a server to join on launch</string> <string>Set a world to join on launch</string>
</property> </property>
<property name="checkable"> <property name="checkable">
<bool>true</bool> <bool>true</bool>
@ -466,15 +466,9 @@
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_11"> <layout class="QVBoxLayout" name="verticalLayout_11">
<item> <item>
<layout class="QGridLayout" name="serverJoinLayout"> <layout class="QGridLayout" name="quickPlayLayout">
<item row="0" column="0"> <item row="0" column="0">
<widget class="QLabel" name="serverJoinAddressLabel"> <widget class="QRadioButton" name="serverAddressRadioButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text"> <property name="text">
<string>Server address:</string> <string>Server address:</string>
</property> </property>
@ -483,6 +477,16 @@
<item row="0" column="1"> <item row="0" column="1">
<widget class="QLineEdit" name="serverJoinAddress"/> <widget class="QLineEdit" name="serverJoinAddress"/>
</item> </item>
<item row="1" column="0">
<widget class="QRadioButton" name="worldRadioButton">
<property name="text">
<string>Singleplayer world:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="worldsComboBox"/>
</item>
</layout> </layout>
</item> </item>
</layout> </layout>

View File

@ -762,7 +762,8 @@ void ServersPage::on_actionMove_Down_triggered()
void ServersPage::on_actionJoin_triggered() void ServersPage::on_actionJoin_triggered()
{ {
const auto &address = m_model->at(currentServer)->m_address; const auto &address = m_model->at(currentServer)->m_address;
APPLICATION->launch(m_inst, true, nullptr, std::make_shared<MinecraftServerTarget>(MinecraftServerTarget::parse(address))); APPLICATION->launch(m_inst, true, nullptr, std::make_shared<QuickPlayTarget>(
QuickPlayTarget::parseMultiplayer(address)));
} }
#include "ServersPage.moc" #include "ServersPage.moc"

View File

@ -1,4 +1,4 @@
/* Copyright 2015-2021 MultiMC Contributors /* Copyright 2015-2023 MultiMC Contributors
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -24,7 +24,6 @@
#include <QMessageBox> #include <QMessageBox>
#include <QTreeView> #include <QTreeView>
#include <QInputDialog> #include <QInputDialog>
#include <QProcess>
#include "tools/MCEditTool.h" #include "tools/MCEditTool.h"
#include "FileSystem.h" #include "FileSystem.h"
@ -32,6 +31,9 @@
#include "ui/GuiUtil.h" #include "ui/GuiUtil.h"
#include "DesktopServices.h" #include "DesktopServices.h"
#include "minecraft/PackProfile.h"
#include "minecraft/VersionFilterData.h"
#include "Application.h" #include "Application.h"
@ -62,7 +64,7 @@ public:
}; };
WorldListPage::WorldListPage(BaseInstance *inst, std::shared_ptr<WorldList> worlds, QWidget *parent) WorldListPage::WorldListPage(InstancePtr inst, std::shared_ptr<WorldList> worlds, QWidget *parent)
: QMainWindow(parent), m_inst(inst), ui(new Ui::WorldListPage), m_worlds(worlds) : QMainWindow(parent), m_inst(inst), ui(new Ui::WorldListPage), m_worlds(worlds)
{ {
ui->setupUi(this); ui->setupUi(this);
@ -311,8 +313,15 @@ void WorldListPage::mceditState(LoggedProcess::State state)
void WorldListPage::worldChanged(const QModelIndex &current, const QModelIndex &previous) void WorldListPage::worldChanged(const QModelIndex &current, const QModelIndex &previous)
{ {
auto mcInst = std::dynamic_pointer_cast<MinecraftInstance>(m_inst);
bool enableJoinActions = mcInst && mcInst->getPackProfile()->getComponent("net.minecraft")->getReleaseDateTime() >= g_VersionFilterData.quickPlayBeginsDate;
QModelIndex index = getSelectedWorld(); QModelIndex index = getSelectedWorld();
bool enable = index.isValid(); bool enable = index.isValid();
ui->actionJoin->setVisible(enableJoinActions);
ui->actionJoinOffline->setVisible(enableJoinActions);
ui->actionJoin->setEnabled(enable && enableJoinActions);
ui->actionJoinOffline->setEnabled(enable && enableJoinActions);
ui->actionCopy_Seed->setEnabled(enable); ui->actionCopy_Seed->setEnabled(enable);
ui->actionMCEdit->setEnabled(enable); ui->actionMCEdit->setEnabled(enable);
ui->actionRemove->setEnabled(enable); ui->actionRemove->setEnabled(enable);
@ -409,4 +418,29 @@ void WorldListPage::on_actionRefresh_triggered()
m_worlds->update(); m_worlds->update();
} }
void WorldListPage::joinSelectedWorld(bool online)
{
auto index = getSelectedWorld();
if (!index.isValid())
{
return;
}
auto worldVariant = m_worlds->data(index, WorldList::ObjectRole);
auto world = (World *) worldVariant.value<void *>();
auto name = world->folderName();
APPLICATION->launch(m_inst, online, nullptr, std::make_shared<QuickPlayTarget>(QuickPlayTarget::parseSingleplayer(name)));
}
void WorldListPage::on_actionJoin_triggered()
{
joinSelectedWorld(true);
}
void WorldListPage::on_actionJoinOffline_triggered()
{
joinSelectedWorld(false);
}
#include "WorldListPage.moc" #include "WorldListPage.moc"

View File

@ -1,4 +1,4 @@
/* Copyright 2015-2021 MultiMC Contributors /* Copyright 2015-2023 MultiMC Contributors
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -34,7 +34,7 @@ class WorldListPage : public QMainWindow, public BasePage
public: public:
explicit WorldListPage( explicit WorldListPage(
BaseInstance *inst, InstancePtr inst,
std::shared_ptr<WorldList> worlds, std::shared_ptr<WorldList> worlds,
QWidget *parent = 0 QWidget *parent = 0
); );
@ -67,13 +67,14 @@ protected:
QMenu * createPopupMenu() override; QMenu * createPopupMenu() override;
protected: protected:
BaseInstance *m_inst; InstancePtr m_inst;
private: private:
QModelIndex getSelectedWorld(); QModelIndex getSelectedWorld();
bool isWorldSafe(QModelIndex index); bool isWorldSafe(QModelIndex index);
bool worldSafetyNagQuestion(); bool worldSafetyNagQuestion();
void mceditError(); void mceditError();
void joinSelectedWorld(bool online);
private: private:
Ui::WorldListPage *ui; Ui::WorldListPage *ui;
@ -92,6 +93,8 @@ private slots:
void on_actionView_Folder_triggered(); void on_actionView_Folder_triggered();
void on_actionDatapacks_triggered(); void on_actionDatapacks_triggered();
void on_actionReset_Icon_triggered(); void on_actionReset_Icon_triggered();
void on_actionJoin_triggered();
void on_actionJoinOffline_triggered();
void worldChanged(const QModelIndex &current, const QModelIndex &previous); void worldChanged(const QModelIndex &current, const QModelIndex &previous);
void mceditState(LoggedProcess::State state); void mceditState(LoggedProcess::State state);

View File

@ -81,6 +81,8 @@
</attribute> </attribute>
<addaction name="actionAdd"/> <addaction name="actionAdd"/>
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="actionJoin"/>
<addaction name="actionJoinOffline"/>
<addaction name="actionRename"/> <addaction name="actionRename"/>
<addaction name="actionCopy"/> <addaction name="actionCopy"/>
<addaction name="actionRemove"/> <addaction name="actionRemove"/>
@ -97,6 +99,22 @@
<string>Add</string> <string>Add</string>
</property> </property>
</action> </action>
<action name="actionJoin">
<property name="text">
<string>Join</string>
</property>
<property name="toolTip">
<string>Launch the instance directly into the selected world</string>
</property>
</action>
<action name="actionJoinOffline">
<property name="text">
<string>Join offline</string>
</property>
<property name="toolTip">
<string>Launch the instance in offline mode directly into the selected world</string>
</property>
</action>
<action name="actionRename"> <action name="actionRename">
<property name="text"> <property name="text">
<string>Rename</string> <string>Rename</string>

View File

@ -20,7 +20,6 @@ private slots:
setText(m_action->text()); setText(m_action->text());
setIcon(m_action->icon()); setIcon(m_action->icon());
setToolTip(m_action->toolTip()); setToolTip(m_action->toolTip());
setHidden(!m_action->isVisible());
setFocusPolicy(Qt::NoFocus); setFocusPolicy(Qt::NoFocus);
} }
private: private:
@ -63,6 +62,9 @@ void WideBar::addAction(QAction* action)
{ {
auto entry = new BarEntry(); auto entry = new BarEntry();
entry->qAction = addWidget(new ActionButton(action, this)); entry->qAction = addWidget(new ActionButton(action, this));
connect(action, &QAction::changed, entry->qAction, [entry, action](){
entry->qAction->setVisible(action->isVisible());
});
entry->wideAction = action; entry->wideAction = action;
entry->type = BarEntry::Action; entry->type = BarEntry::Action;
m_entries.push_back(entry); m_entries.push_back(entry);

View File

@ -55,6 +55,8 @@ public class OneSixLauncher implements Launcher
private String serverPort; private String serverPort;
private boolean useQuickPlay; private boolean useQuickPlay;
private String joinWorld;
// the much abused system classloader, for convenience (for further abuse) // the much abused system classloader, for convenience (for further abuse)
private ClassLoader cl; private ClassLoader cl;
@ -82,6 +84,7 @@ public class OneSixLauncher implements Launcher
serverAddress = params.firstSafe("serverAddress", null); serverAddress = params.firstSafe("serverAddress", null);
serverPort = params.firstSafe("serverPort", null); serverPort = params.firstSafe("serverPort", null);
useQuickPlay = params.firstSafe("useQuickPlay").startsWith("1"); useQuickPlay = params.firstSafe("useQuickPlay").startsWith("1");
joinWorld = params.firstSafe("joinWorld", null);
cwd = System.getProperty("user.dir"); cwd = System.getProperty("user.dir");
@ -185,6 +188,12 @@ public class OneSixLauncher implements Launcher
mcparams.add(Integer.toString(winSizeH)); mcparams.add(Integer.toString(winSizeH));
} }
if (joinWorld != null)
{
mcparams.add("--quickPlaySingleplayer");
mcparams.add(joinWorld);
}
if (serverAddress != null) if (serverAddress != null)
{ {
if (useQuickPlay) if (useQuickPlay)