From b6bfc494e6dcaba4a5b15797f437c1dfa2886234 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Wed, 5 Nov 2025 13:23:48 +0100 Subject: [PATCH] Fix singleplayer with --gameid and new world --- src/client/clientlauncher.cpp | 61 +++++++++++++++++------------------ src/content/subgames.cpp | 6 ++-- src/main.cpp | 20 +++++------- 3 files changed, 42 insertions(+), 45 deletions(-) diff --git a/src/client/clientlauncher.cpp b/src/client/clientlauncher.cpp index 59b8ddbab7..be190b9e25 100644 --- a/src/client/clientlauncher.cpp +++ b/src/client/clientlauncher.cpp @@ -274,6 +274,15 @@ void ClientLauncher::init_args(GameStartData &start_data, const Settings &cmd_ar if (cmd_args.exists("name")) start_data.name = cmd_args.get("name"); + // If a world was commanded, select it + if (!start_data.world_path.empty()) { + auto &spec = start_data.world_spec; + + spec.path = start_data.world_path; + spec.gameid = getWorldGameId(spec.path, true); + spec.name = _("[--world parameter]"); + } + random_input = g_settings->getBool("random_input") || cmd_args.getFlag("random-input"); } @@ -413,17 +422,8 @@ bool ClientLauncher::launch_game(std::string &error_message, } } - // If a world was commanded, append and select it - // This is provieded by "get_world_from_cmdline()", main.cpp - if (!start_data.world_path.empty()) { - auto &spec = start_data.world_spec; - - spec.path = start_data.world_path; - spec.gameid = getWorldGameId(spec.path, true); - spec.name = _("[--world parameter]"); - } - - /* Show the GUI menu + /* + * Show the GUI menu */ std::string server_name, server_description; if (!skip_main_menu) { @@ -440,7 +440,7 @@ bool ClientLauncher::launch_game(std::string &error_message, main_menu(&menudata); // Skip further loading if there was an exit signal. - if (*porting::signal_handler_killstatus()) + if (!m_rendering_engine->run() || *porting::signal_handler_killstatus()) return false; if (!menudata.script_data.errormessage.empty()) { @@ -461,6 +461,7 @@ bool ClientLauncher::launch_game(std::string &error_message, int world_index = menudata.selected_world; if (world_index >= 0 && world_index < (int)worldspecs.size()) { start_data.world_spec = worldspecs[world_index]; + start_data.world_path = start_data.world_spec.path; } start_data.name = menudata.name; @@ -477,9 +478,6 @@ bool ClientLauncher::launch_game(std::string &error_message, start_data.address.empty() && !start_data.name.empty(); } - if (!m_rendering_engine->run()) - return false; - if (!start_data.isSinglePlayer() && start_data.name.empty()) { error_message = gettext("Please choose a name!"); errorstream << error_message << std::endl; @@ -502,12 +500,9 @@ bool ClientLauncher::launch_game(std::string &error_message, return false; } - auto &worldspec = start_data.world_spec; - infostream << "Selected world: " << worldspec.name - << " [" << worldspec.path << "]" << std::endl; - + // For singleplayer and local server if (start_data.address.empty()) { - // For singleplayer and local server + auto &worldspec = start_data.world_spec; if (worldspec.path.empty()) { error_message = gettext("No world selected and no address " "provided. Nothing to do."); @@ -515,26 +510,30 @@ bool ClientLauncher::launch_game(std::string &error_message, return false; } - if (!fs::PathExists(worldspec.path)) { - error_message = gettext("Provided world path doesn't exist: ") - + worldspec.path; - errorstream << error_message << std::endl; - return false; + infostream << "Selected world: " << worldspec.name + << " [" << worldspec.path << "]" << std::endl; + + // Figure out which game we'll be using + // Note that start_data.game_spec contains the gameid from the command line + bool world_exists = getWorldExists(worldspec.path); + if (world_exists) { + auto world_game = findWorldSubgame(worldspec.path); + if (world_game.isValid()) + start_data.game_spec = world_game; } - // Load gamespec for required game - start_data.game_spec = findWorldSubgame(worldspec.path); if (!start_data.game_spec.isValid()) { - error_message = gettext("Could not find or load game: ") + if (world_exists) { + error_message = gettext("Could not find or load game: ") + worldspec.gameid; + } else { + error_message = gettext("World does not exist and no game selected to create one."); + } errorstream << error_message << std::endl; return false; } - - return true; } - start_data.world_path = start_data.world_spec.path; return true; } diff --git a/src/content/subgames.cpp b/src/content/subgames.cpp index e9e3a72d81..e9d2c1d69c 100644 --- a/src/content/subgames.cpp +++ b/src/content/subgames.cpp @@ -237,9 +237,11 @@ std::vector getAvailableGames() bool getWorldExists(const std::string &world_path) { + if (world_path.empty()) + return false; // Note: very old worlds are valid without a world.mt - return (fs::PathExists(world_path + DIR_DELIM + "map_meta.txt") || - fs::PathExists(world_path + DIR_DELIM + "world.mt")); + return (fs::IsFile(world_path + DIR_DELIM + "map_meta.txt") || + fs::IsFile(world_path + DIR_DELIM + "world.mt")); } //! Try to get the displayed name of a world diff --git a/src/main.cpp b/src/main.cpp index 3eb6076604..5153911591 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1041,8 +1041,7 @@ static bool get_game_from_cmdline(GameParams *game_params, const Settings &cmd_a errorstream << "Game \"" << gameid << "\" not found" << std::endl; return false; } - dstream << _("Using game specified by --gameid on the command line") - << std::endl; + infostream << "Using commanded gameid [" << commanded_gamespec.id << "]" << std::endl; game_params->game_spec = commanded_gamespec; return true; } @@ -1052,18 +1051,19 @@ static bool get_game_from_cmdline(GameParams *game_params, const Settings &cmd_a static bool determine_subgame(GameParams *game_params) { - SubgameSpec gamespec; + if (!game_params->is_dedicated_server) { + // ClientLauncher has its own logic to choose a game + return true; + } + SubgameSpec gamespec; assert(!game_params->world_path.empty()); // Pre-condition - // If world doesn't exist - if (!game_params->world_path.empty() - && !getWorldExists(game_params->world_path)) { + if (!getWorldExists(game_params->world_path)) { // Try to take gamespec from command line if (game_params->game_spec.isValid()) { gamespec = game_params->game_spec; - infostream << "Using commanded gameid [" << gamespec.id << "]" << std::endl; - } else if (game_params->is_dedicated_server) { + } else { auto games = getAvailableGameIds(); // If there's exactly one obvious choice then do the right thing if (games.size() > 1) @@ -1094,16 +1094,12 @@ static bool determine_subgame(GameParams *game_params) << world_gameid << "]" << std::endl; } } else { - // If world contains an embedded game, use it; - // Otherwise find world from local system. gamespec = findWorldSubgame(game_params->world_path); infostream << "Using world gameid [" << gamespec.id << "]" << std::endl; } } if (!gamespec.isValid()) { - if (!game_params->is_dedicated_server) - return true; // not an error, this would prevent the main menu from running errorstream << "Game [" << gamespec.id << "] could not be found." << std::endl; return false;