Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 36 additions & 2 deletions launcher/Application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,18 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
return;
}

if (m_instanceIdToLaunch.isEmpty() && !m_worldToJoin.isEmpty()) {
qWarning() << "--world can only be used in combination with --launch!";
m_status = Application::Failed;
return;
}

if (!m_serverToJoin.isEmpty() && !m_worldToJoin.isEmpty()) {
qWarning() << "--server and --world cannot be used together!";
m_status = Application::Failed;
return;
}

if (m_instanceIdToLaunch.isEmpty() && !m_profileToUse.isEmpty()) {
qWarning()
<< "--profile can only be used in combination with --launch!";
Expand Down Expand Up @@ -504,6 +516,13 @@ QHash<QString, QVariant> Application::parseCommandLine(int& argc, char** argv)
parser.addDocumentation("server",
"Join the specified server on launch (only valid "
"in combination with --launch)");
// --world
parser.addOption("world");
parser.addShortOpt("world", 'w');
parser.addDocumentation("world",
"Open the specified singleplayer world on launch, "
"by its save folder name (only valid in "
"combination with --launch)");
// --profile
parser.addOption("profile");
parser.addShortOpt("profile", 'a');
Expand Down Expand Up @@ -571,6 +590,7 @@ QHash<QString, QVariant> Application::parseCommandLine(int& argc, char** argv)

m_instanceIdToLaunch = args["launch"].toString();
m_serverToJoin = args["server"].toString();
m_worldToJoin = args["world"].toString();
m_profileToUse = args["profile"].toString();
m_liveCheck = args["alive"].toBool();
m_zipToImport = args["import"].toUrl();
Expand Down Expand Up @@ -732,6 +752,9 @@ bool Application::initPeerInstance()
if (!m_serverToJoin.isEmpty()) {
launch.args["server"] = m_serverToJoin;
}
if (!m_worldToJoin.isEmpty()) {
launch.args["world"] = m_worldToJoin;
}
if (!m_profileToUse.isEmpty()) {
launch.args["profile"] = m_profileToUse;
}
Expand Down Expand Up @@ -822,6 +845,9 @@ void Application::setupPaths(const QString& binPath, const QString& origcwdPath,
if (!m_serverToJoin.isEmpty()) {
qInfo().noquote() << "Address of server to join :" << m_serverToJoin;
}
if (!m_worldToJoin.isEmpty()) {
qInfo().noquote() << "Name of world to join :" << m_worldToJoin;
}
qInfo().noquote() << "<> Paths set.";

if (m_liveCheck) {
Expand Down Expand Up @@ -1490,8 +1516,12 @@ void Application::performMainStartupAction()
if (!m_serverToJoin.isEmpty()) {
// FIXME: validate the server string
serverToJoin.reset(new MinecraftServerTarget(
MinecraftServerTarget::parse(m_serverToJoin)));
MinecraftServerTarget::parse(m_serverToJoin, false)));
qDebug() << " Launching with server" << m_serverToJoin;
} else if (!m_worldToJoin.isEmpty()) {
serverToJoin.reset(new MinecraftServerTarget(
MinecraftServerTarget::parse(m_worldToJoin, true)));
qDebug() << " Launching with world" << m_worldToJoin;
}

if (!m_profileToUse.isEmpty()) {
Expand Down Expand Up @@ -1576,6 +1606,7 @@ void Application::messageReceived(const QByteArray& message)
} else if (command == "launch") {
QString id = received.args["id"];
QString server = received.args["server"];
QString world = received.args["world"];
QString profile = received.args["profile"];

InstancePtr instance;
Expand All @@ -1594,7 +1625,10 @@ void Application::messageReceived(const QByteArray& message)
MinecraftServerTargetPtr serverObject = nullptr;
if (!server.isEmpty()) {
serverObject = std::make_shared<MinecraftServerTarget>(
MinecraftServerTarget::parse(server));
MinecraftServerTarget::parse(server, false));
} else if (!world.isEmpty()) {
serverObject = std::make_shared<MinecraftServerTarget>(
MinecraftServerTarget::parse(world, true));
}

MinecraftAccountPtr accountObject;
Expand Down
3 changes: 3 additions & 0 deletions launcher/Application.h
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,9 @@ class Application : public QApplication
public:
QString m_instanceIdToLaunch;
QString m_serverToJoin;
/* Save folder name of a world to open on launch, from --world. Mutually
* exclusive with m_serverToJoin; startup rejects both being set. */
QString m_worldToJoin;
QString m_profileToUse;
bool m_liveCheck = false;
QUrl m_zipToImport;
Expand Down
20 changes: 16 additions & 4 deletions launcher/minecraft/MinecraftInstance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -569,8 +569,17 @@ QStringList MinecraftInstance::processMinecraftArgs(
}

if (serverToJoin && !serverToJoin->address.isEmpty()) {
args_pattern += " --server " + serverToJoin->address;
args_pattern += " --port " + QString::number(serverToJoin->port);
if (profile->hasTrait("feature:is_quick_play_multiplayer")) {
args_pattern += " --quickPlayMultiplayer " +
serverToJoin->address + ":" +
QString::number(serverToJoin->port);
} else {
args_pattern += " --server " + serverToJoin->address;
args_pattern += " --port " + QString::number(serverToJoin->port);
}
} else if (serverToJoin && !serverToJoin->world.isEmpty() &&
profile->hasTrait("feature:is_quick_play_singleplayer")) {
args_pattern += " --quickPlaySingleplayer " + serverToJoin->world;
}

QMap<QString, QString> token_mapping;
Expand Down Expand Up @@ -636,6 +645,8 @@ MinecraftInstance::createLaunchScript(AuthSessionPtr session,
launchScript += "serverAddress " + serverToJoin->address + "\n";
launchScript +=
"serverPort " + QString::number(serverToJoin->port) + "\n";
} else if (serverToJoin && !serverToJoin->world.isEmpty()) {
launchScript += "worldName " + serverToJoin->world + "\n";
}

// generic minecraft params
Expand Down Expand Up @@ -1016,10 +1027,11 @@ MinecraftInstance::createLaunchTask(AuthSessionPtr session,
QString fullAddress =
m_settings->get("JoinServerOnLaunchAddress").toString();
serverToJoin.reset(new MinecraftServerTarget(
MinecraftServerTarget::parse(fullAddress)));
MinecraftServerTarget::parse(fullAddress, false)));
}

if (serverToJoin && serverToJoin->port == 25565) {
if (serverToJoin && !serverToJoin->address.isEmpty() &&
serverToJoin->port == 25565) {
// Resolve server address to join on launch
auto* step = new LookupServerAddress(pptr);
step->setLookupAddress(serverToJoin->address);
Expand Down
11 changes: 9 additions & 2 deletions launcher/minecraft/launch/MinecraftServerTarget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,15 @@

// 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)
MinecraftServerTarget MinecraftServerTarget::parse(const QString& fullAddress,
bool useWorld)
{
if (useWorld) {
MinecraftServerTarget target;
target.world = fullAddress;
return target;
}

QStringList split = fullAddress.split(":");

// The logic below replicates the exact logic minecraft uses for parsing
Expand Down Expand Up @@ -63,5 +70,5 @@ MinecraftServerTarget MinecraftServerTarget::parse(const QString& fullAddress)
}
}

return MinecraftServerTarget{realAddress, realPort};
return MinecraftServerTarget{realAddress, realPort, QString()};
}
7 changes: 5 additions & 2 deletions launcher/minecraft/launch/MinecraftServerTarget.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,12 @@

struct MinecraftServerTarget {
QString address;
quint16 port;
quint16 port = 25565;

static MinecraftServerTarget parse(const QString& fullAddress);
QString world;

static MinecraftServerTarget parse(const QString& fullAddress,
bool useWorld);
};

typedef std::shared_ptr<MinecraftServerTarget> MinecraftServerTargetPtr;
6 changes: 1 addition & 5 deletions launcher/ui/dialogs/CreateShortcutDialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ CreateShortcutDialog::CreateShortcutDialog(MinecraftInstance* instance,
tr("%1 [%2] - Last Played: %3")
.arg(world.name(), world.gameType().toTranslatedString(),
world.lastPlayed().toString(Qt::ISODate)),
world.name());
world.folderName());
}
}

Expand Down Expand Up @@ -213,10 +213,6 @@ void CreateShortcutDialog::createShortcut()

if (ui->targetCheckbox->isChecked()) {
if (ui->worldTarget->isChecked()) {
/* Unreachable while m_canJoinWorld is always false. When
* quick play does arrive, --world has to be added to the
* command line in Application.cpp alongside --server, or
* the shortcut this writes will be rejected on startup. */
shortcut.targetString = tr("world");
shortcut.extraArgs
<< QStringLiteral("--world")
Expand Down
2 changes: 1 addition & 1 deletion launcher/ui/pages/instance/ServersPage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -727,7 +727,7 @@ void ServersPage::on_actionJoin_triggered()
const auto& address = m_model->at(currentServer)->m_address;
APPLICATION->launch(m_inst, LaunchMode::Normal,
std::make_shared<MinecraftServerTarget>(
MinecraftServerTarget::parse(address)));
MinecraftServerTarget::parse(address, false)));
}

#include "ServersPage.moc"
49 changes: 41 additions & 8 deletions libraries/launcher/org/projecttick/modern/ModernLauncher.java
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@
* natives - Path to the native libraries directory
* serverAddress - Server address for direct-connect on launch (optional)
* serverPort - Server port for direct-connect on launch (optional)
* worldName - Singleplayer world save folder to open on launch (optional)
* traits - Version traits, used to pick quick play vs. legacy args
*/
public class ModernLauncher implements MeshMC
{
Expand Down Expand Up @@ -124,21 +126,52 @@ private int doLaunch(ParamBucket params) throws Exception
params.allSafe("param", Collections.<String>emptyList())
);

// Direct-connect: server address / port are passed as separate keys and
// must be appended to game args manually (processMinecraftArgs skips them
// when a launch script is used).
// Launch destination: a server or a world, never both. Passed as
// separate keys and appended here rather than by the C++ side, because
// processMinecraftArgs skips them when a launch script is used.
//
// Which argument the game understands depends on its version:
// Minecraft 1.20 (23w14a) removed --server/--port and replaced them
// with quick play. The version's traits say which it is, so ask them
// instead of guessing -- passing the wrong pair makes the game either
// ignore the destination or refuse to start.
List<String> traits = params.allSafe("traits", Collections.<String>emptyList());
boolean quickPlayMultiplayer = traits.contains("feature:is_quick_play_multiplayer");
boolean quickPlaySingleplayer = traits.contains("feature:is_quick_play_singleplayer");

String serverAddress = params.firstSafe("serverAddress", "");
String serverPort = params.firstSafe("serverPort", "");
String worldName = params.firstSafe("worldName", "");

if (serverAddress != null && !serverAddress.isEmpty())
{
gameArgs.add("--server");
gameArgs.add(serverAddress);
if (serverPort != null && !serverPort.isEmpty())
if (quickPlayMultiplayer)
{
gameArgs.add("--quickPlayMultiplayer");
// quickPlayMultiplayer takes one "host:port" argument, so an
// absent port has to become the default rather than nothing.
String port = (serverPort == null || serverPort.isEmpty()) ? "25565" : serverPort;
gameArgs.add(serverAddress + ":" + port);
}
else
{
gameArgs.add("--port");
gameArgs.add(serverPort);
gameArgs.add("--server");
gameArgs.add(serverAddress);
if (serverPort != null && !serverPort.isEmpty())
{
gameArgs.add("--port");
gameArgs.add(serverPort);
}
}
}
else if (worldName != null && !worldName.isEmpty() && quickPlaySingleplayer)
{
// No pre-quick-play way to open a world exists, so unlike the
// server case there is nothing to fall back to: a version without
// the trait just launches to the main menu.
gameArgs.add("--quickPlaySingleplayer");
gameArgs.add(worldName);
}

// --- Build the full command ---
List<String> command = buildCommand(javaPath, jvmArgs, natives, classpath, mainClass, gameArgs);
Expand Down
Loading