diff --git a/src/arma3-unix-launcher-library/arma3client.cpp b/src/arma3-unix-launcher-library/arma3client.cpp index c407c41..dbb17d0 100644 --- a/src/arma3-unix-launcher-library/arma3client.cpp +++ b/src/arma3-unix-launcher-library/arma3client.cpp @@ -237,6 +237,15 @@ namespace ARMA3 std::vector Client::GetWorkshopMods() { + auto const workshop_path = GetPathWorkshop(); + + /* + * workshop directory may not exist, in case where we don't have any mods subscribed + * if parent path does not exist, then something is seriously broken and it should fail visibly + */ + if (!FilesystemUtils::Exists(workshop_path) && FilesystemUtils::Exists(workshop_path.parent_path())) + return {}; + return GetModsFromDirectory(GetPathWorkshop()); } diff --git a/src/arma3-unix-launcher-library/steam_utils.cpp b/src/arma3-unix-launcher-library/steam_utils.cpp index 78feae5..af1f172 100644 --- a/src/arma3-unix-launcher-library/steam_utils.cpp +++ b/src/arma3-unix-launcher-library/steam_utils.cpp @@ -91,7 +91,7 @@ path SteamUtils::GetGamePathFromInstallPath(path const &install_path, std::strin path SteamUtils::GetWorkshopPath(path const &install_path, std::string const &appid) const { path proposed_path = install_path / "steamapps/workshop/content" / appid; - if (fs::Exists(proposed_path)) + if (fs::Exists(proposed_path.parent_path())) return proposed_path; throw SteamWorkshopDirectoryNotFoundException(appid); diff --git a/src/arma3-unix-launcher/main.cpp b/src/arma3-unix-launcher/main.cpp index b69e1d8..c706734 100644 --- a/src/arma3-unix-launcher/main.cpp +++ b/src/arma3-unix-launcher/main.cpp @@ -147,7 +147,14 @@ int main(int argc, char *argv[]) { spdlog::info("Install path: '{}'", path); arma_path = steam.GetGamePathFromInstallPath(path, ARMA3::Definitions::app_id); - workshop_path = steam.GetWorkshopPath(path, ARMA3::Definitions::app_id); + try + { + workshop_path = steam.GetWorkshopPath(path, ARMA3::Definitions::app_id); + } + catch (std::exception const &e) // todo: write macro for this? ex. TRY() + { + spdlog::warn("Arma path is correct '{}', failed getting workshop path: '{}'", arma_path, e.what()); + } client = std::make_unique(arma_path, workshop_path); break; } @@ -207,7 +214,7 @@ int main(int argc, char *argv[]) return 0; } - MainWindow w(std::move(client), config_file, parser.get("--disable-steam-integration")); + MainWindow w(std::move(client), config_file, !parser.get("--disable-steam-integration")); w.show(); return a.exec(); diff --git a/src/dayz-linux-launcher-library/dayzclient.cpp b/src/dayz-linux-launcher-library/dayzclient.cpp index eb28f2e..5fc9027 100644 --- a/src/dayz-linux-launcher-library/dayzclient.cpp +++ b/src/dayz-linux-launcher-library/dayzclient.cpp @@ -174,6 +174,15 @@ namespace DayZ std::vector Client::GetWorkshopMods() { + auto const workshop_path = GetPathWorkshop(); + + /* + * workshop directory may not exist, in case where we don't have any mods subscribed + * if parent path does not exist, then something is seriously broken and it should fail visibly + */ + if (!FilesystemUtils::Exists(workshop_path) && FilesystemUtils::Exists(workshop_path.parent_path())) + return {}; + return GetModsFromDirectory(GetPathWorkshop()); } diff --git a/src/dayz-linux-launcher/main.cpp b/src/dayz-linux-launcher/main.cpp index 4aa067b..3117ab4 100644 --- a/src/dayz-linux-launcher/main.cpp +++ b/src/dayz-linux-launcher/main.cpp @@ -146,6 +146,14 @@ int main(int argc, char *argv[]) { spdlog::info("Install path: '{}'", path); arma_path = steam.GetGamePathFromInstallPath(path, DayZ::Definitions::app_id); + try + { + workshop_path = steam.GetWorkshopPath(path, ARMA3::Definitions::app_id); + } + catch (std::exception const &e) // todo: write macro for this? ex. TRY() + { + spdlog::warn("DayZ path is correct '{}', failed getting workshop path: '{}'", arma_path, e.what()); + } workshop_path = steam.GetWorkshopPath(path, DayZ::Definitions::app_id); client = std::make_unique(arma_path, workshop_path); break; @@ -206,7 +214,7 @@ int main(int argc, char *argv[]) return 0; } - MainWindow w(std::move(client), config_file, parser.get("--disable-steam-integration")); + MainWindow w(std::move(client), config_file, !parser.get("--disable-steam-integration")); w.show(); return a.exec(); diff --git a/tests/unit/arma3-unix-launcher-library/test_arma3client.cpp b/tests/unit/arma3-unix-launcher-library/test_arma3client.cpp index f5846cf..d4bade8 100644 --- a/tests/unit/arma3-unix-launcher-library/test_arma3client.cpp +++ b/tests/unit/arma3-unix-launcher-library/test_arma3client.cpp @@ -204,44 +204,57 @@ TEST_CASE_FIXTURE(ARMA3ClientTests, "GetWorkshopMods") { REQUIRE_CALL(filesystemUtilsMock, Exists(get_executable_path())).RETURN(true); ARMA3::Client a3c(arma_path, workshop_path); - WHEN("Workshop directory does not contain mods") + WHEN("Workshop directory does not exist") { - REQUIRE_CALL(filesystemUtilsMock, Ls(workshop_path, _)).RETURN(std::vector {}); + REQUIRE_CALL(filesystemUtilsMock, Exists(workshop_path)).RETURN(false); + REQUIRE_CALL(filesystemUtilsMock, Exists(workshop_path.parent_path())).RETURN(true); THEN("Returned vector is empty") { CHECK(a3c.GetWorkshopMods().empty()); } } - WHEN("Workshop directory contains only two directories with useless files inside") + WHEN("Workshop directory exists") { - std::array const mod_names{"123", "456"}; - std::array const mod_paths{workshop_path / mod_names[0], workshop_path / mod_names[1]}; - REQUIRE_CALL(filesystemUtilsMock, Ls(workshop_path, _)).RETURN(std::vector {mod_paths[0], mod_paths[1]}); - REQUIRE_CALL(filesystemUtilsMock, IsDirectory(mod_paths[0])).RETURN(true); - REQUIRE_CALL(filesystemUtilsMock, Ls(mod_paths[0], _)).RETURN(std::vector {"useless.bin"}); - REQUIRE_CALL(filesystemUtilsMock, IsDirectory(mod_paths[1])).RETURN(true); - REQUIRE_CALL(filesystemUtilsMock, Ls(mod_paths[1], _)).RETURN(std::vector {"useless.bin"}); - THEN("Returned vector is empty") + REQUIRE_CALL(filesystemUtilsMock, Exists(workshop_path)).RETURN(true); + WHEN("Workshop directory does not contain mods") { - CHECK(a3c.GetWorkshopMods().empty()); + REQUIRE_CALL(filesystemUtilsMock, Ls(workshop_path, _)).RETURN(std::vector {}); + THEN("Returned vector is empty") + { + CHECK(a3c.GetWorkshopMods().empty()); + } } - } - WHEN("Workshop directory contains two directories with workshop mods inside") - { - std::array const mod_names{"123", "456"}; - std::array const mod_paths{workshop_path / mod_names[0], workshop_path / mod_names[1]}; - REQUIRE_CALL(filesystemUtilsMock, Ls(workshop_path, _)).RETURN(std::vector {mod_paths[0], mod_paths[1]}); - REQUIRE_CALL(filesystemUtilsMock, IsDirectory(mod_paths[0])).RETURN(true); - REQUIRE_CALL(filesystemUtilsMock, Ls(mod_paths[0], _)).RETURN(std::vector {"addons"}); - REQUIRE_CALL(modMock, Constructor(mod_paths[0], _)); - REQUIRE_CALL(filesystemUtilsMock, IsDirectory(mod_paths[1])).RETURN(true); - REQUIRE_CALL(filesystemUtilsMock, Ls(mod_paths[1], _)).RETURN(std::vector {"addons"}); - REQUIRE_CALL(modMock, Constructor(mod_paths[1], _)); - THEN("Returned vector is empty") + WHEN("Workshop directory contains only two directories with useless files inside") { - auto mods = a3c.GetWorkshopMods(); - CHECK_EQ(mod_paths[0], mods[0].path_); - CHECK_EQ(mod_paths[1], mods[1].path_); + std::array const mod_names{"123", "456"}; + std::array const mod_paths{workshop_path / mod_names[0], workshop_path / mod_names[1]}; + REQUIRE_CALL(filesystemUtilsMock, Ls(workshop_path, _)).RETURN(std::vector {mod_paths[0], mod_paths[1]}); + REQUIRE_CALL(filesystemUtilsMock, IsDirectory(mod_paths[0])).RETURN(true); + REQUIRE_CALL(filesystemUtilsMock, Ls(mod_paths[0], _)).RETURN(std::vector {"useless.bin"}); + REQUIRE_CALL(filesystemUtilsMock, IsDirectory(mod_paths[1])).RETURN(true); + REQUIRE_CALL(filesystemUtilsMock, Ls(mod_paths[1], _)).RETURN(std::vector {"useless.bin"}); + THEN("Returned vector is empty") + { + CHECK(a3c.GetWorkshopMods().empty()); + } + } + WHEN("Workshop directory contains two directories with workshop mods inside") + { + std::array const mod_names{"123", "456"}; + std::array const mod_paths{workshop_path / mod_names[0], workshop_path / mod_names[1]}; + REQUIRE_CALL(filesystemUtilsMock, Ls(workshop_path, _)).RETURN(std::vector {mod_paths[0], mod_paths[1]}); + REQUIRE_CALL(filesystemUtilsMock, IsDirectory(mod_paths[0])).RETURN(true); + REQUIRE_CALL(filesystemUtilsMock, Ls(mod_paths[0], _)).RETURN(std::vector {"addons"}); + REQUIRE_CALL(modMock, Constructor(mod_paths[0], _)); + REQUIRE_CALL(filesystemUtilsMock, IsDirectory(mod_paths[1])).RETURN(true); + REQUIRE_CALL(filesystemUtilsMock, Ls(mod_paths[1], _)).RETURN(std::vector {"addons"}); + REQUIRE_CALL(modMock, Constructor(mod_paths[1], _)); + THEN("Returned vector is empty") + { + auto mods = a3c.GetWorkshopMods(); + CHECK_EQ(mod_paths[0], mods[0].path_); + CHECK_EQ(mod_paths[1], mods[1].path_); + } } } } diff --git a/tests/unit/arma3-unix-launcher-library/test_steam_utils.cpp b/tests/unit/arma3-unix-launcher-library/test_steam_utils.cpp index e0e945d..7f0935c 100644 --- a/tests/unit/arma3-unix-launcher-library/test_steam_utils.cpp +++ b/tests/unit/arma3-unix-launcher-library/test_steam_utils.cpp @@ -171,43 +171,39 @@ TEST_CASE_FIXTURE(SteamUtilsTests, "GetWorkshopDir_Success") { GIVEN("Valid appid for installed game") { - std::string const invalid_game = "107411"; - std::filesystem::path const expected_workshop_path = default_steam_path / "steamapps/workshop/content" / arma3_workshop_id; - std::filesystem::path const not_existing_workshop_path = default_steam_path / "steamapps/workshop/content" / invalid_game; + std::filesystem::path const parent_workshop_path = default_steam_path / "steamapps/workshop/content"; REQUIRE_CALL(filesystemUtilsMock, Exists(default_config_path)).RETURN(true); REQUIRE_CALL(filesystemUtilsMock, RealPath(default_steam_path)).RETURN(default_steam_path); - REQUIRE_CALL(filesystemUtilsMock, Exists(expected_workshop_path)).RETURN(true); - REQUIRE_CALL(filesystemUtilsMock, Exists(not_existing_workshop_path)).RETURN(false); SteamUtils steam({default_steam_path}); - WHEN("Getting workshop path for installed game") + WHEN("Parent workshop directory exists") { + REQUIRE_CALL(filesystemUtilsMock, Exists(parent_workshop_path)).RETURN(true); THEN("Workshop path for installed game is returned") { - CHECK_EQ(expected_workshop_path, steam.GetWorkshopPath(default_steam_path, arma3_workshop_id)); - CHECK_THROWS_AS(steam.GetWorkshopPath(default_steam_path, invalid_game), SteamWorkshopDirectoryNotFoundException); + CHECK_EQ(parent_workshop_path / arma3_workshop_id, steam.GetWorkshopPath(default_steam_path, arma3_workshop_id)); } } } } -TEST_CASE_FIXTURE(SteamUtilsTests, "GetWorkshopDir_Failed_NotExistingApp") +TEST_CASE_FIXTURE(SteamUtilsTests, "GetWorkshopDir_Failed_ParentDirectoryDoesNotExist") { GIVEN("Valid appid for installed game") { std::string const invalid_game = "107411"; - std::filesystem::path const not_existing_workshop_path = default_steam_path / "steamapps/workshop/content" / invalid_game; + std::filesystem::path const parent_workshop_path = default_steam_path / "steamapps/workshop/content"; REQUIRE_CALL(filesystemUtilsMock, Exists(default_config_path)).RETURN(true); REQUIRE_CALL(filesystemUtilsMock, RealPath(default_steam_path)).RETURN(default_steam_path); - REQUIRE_CALL(filesystemUtilsMock, Exists(not_existing_workshop_path)).RETURN(false); SteamUtils steam({default_steam_path}); - WHEN("Getting workshop path for not installed game") + WHEN("Parent workshop does not exist") { + REQUIRE_CALL(filesystemUtilsMock, Exists(parent_workshop_path)).RETURN(false); THEN("Exception is thrown") { CHECK_THROWS_AS(steam.GetWorkshopPath(default_steam_path, invalid_game), SteamWorkshopDirectoryNotFoundException);