aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRémy Raes <raes.remy@gmail.com>2024-09-08 00:27:44 +0200
committerGitHub <noreply@github.com>2024-09-08 00:27:44 +0200
commit8c546ed68c83b42cdff32d9b848b25ec2cba9c18 (patch)
treee1281836b33a2a1a4b0636fbb74c27ff31407cae
parent160f503bc81bffdef6dbaa16eec7c73fccef0eee (diff)
downloadNorthstarLauncher-8c546ed68c83b42cdff32d9b848b25ec2cba9c18.tar.gz
NorthstarLauncher-8c546ed68c83b42cdff32d9b848b25ec2cba9c18.zip
Adjust for restructured `verified-mods.json` (#748)
Updates the launcher code to deal with adjusted verified mods JSON structure from the default manifest source The idea here is to allow installing mods from other sources than Thunderstore.
-rw-r--r--primedev/mods/autodownload/moddownloader.cpp42
-rw-r--r--primedev/mods/autodownload/moddownloader.h19
2 files changed, 39 insertions, 22 deletions
diff --git a/primedev/mods/autodownload/moddownloader.cpp b/primedev/mods/autodownload/moddownloader.cpp
index 8e533dec..c20a3adb 100644
--- a/primedev/mods/autodownload/moddownloader.cpp
+++ b/primedev/mods/autodownload/moddownloader.cpp
@@ -103,23 +103,23 @@ void ModDownloader::FetchModsListFromAPI()
for (auto i = verifiedModsJson.MemberBegin(); i != verifiedModsJson.MemberEnd(); ++i)
{
// Format testing
- if (!i->value.HasMember("DependencyPrefix") || !i->value.HasMember("Versions"))
+ if (!i->value.HasMember("Repository") || !i->value.HasMember("Versions"))
{
spdlog::warn("Verified mods manifesto format is unrecognized, skipping loading.");
return;
}
std::string name = i->name.GetString();
- std::string dependency = i->value["DependencyPrefix"].GetString();
-
std::unordered_map<std::string, VerifiedModVersion> modVersions;
+
rapidjson::Value& versions = i->value["Versions"];
assert(versions.IsArray());
for (auto& attribute : versions.GetArray())
{
assert(attribute.IsObject());
// Format testing
- if (!attribute.HasMember("Version") || !attribute.HasMember("Checksum"))
+ if (!attribute.HasMember("Version") || !attribute.HasMember("Checksum") || !attribute.HasMember("DownloadLink") ||
+ !attribute.HasMember("Platform"))
{
spdlog::warn("Verified mods manifesto format is unrecognized, skipping loading.");
return;
@@ -127,10 +127,14 @@ void ModDownloader::FetchModsListFromAPI()
std::string version = attribute["Version"].GetString();
std::string checksum = attribute["Checksum"].GetString();
- modVersions.insert({version, {.checksum = checksum}});
+ std::string downloadLink = attribute["DownloadLink"].GetString();
+ std::string platformValue = attribute["Platform"].GetString();
+ VerifiedModPlatform platform =
+ platformValue.compare("thunderstore") == 0 ? VerifiedModPlatform::Thunderstore : VerifiedModPlatform::Unknown;
+ modVersions.insert({version, {.checksum = checksum, .downloadLink = downloadLink, .platform = platform}});
}
- VerifiedModDetails modConfig = {.dependencyPrefix = dependency, .versions = modVersions};
+ VerifiedModDetails modConfig = {.versions = modVersions};
verifiedMods.insert({name, modConfig});
spdlog::info("==> Loaded configuration for mod \"" + name + "\"");
}
@@ -164,13 +168,10 @@ int ModDownloader::ModFetchingProgressCallback(
return 0;
}
-std::optional<fs::path> ModDownloader::FetchModFromDistantStore(std::string_view modName, std::string_view modVersion)
+std::optional<fs::path> ModDownloader::FetchModFromDistantStore(std::string_view modName, VerifiedModVersion version)
{
- // Retrieve mod prefix from local mods list, or use mod name as mod prefix if bypass flag is set
- std::string modPrefix = strstr(GetCommandLineA(), VERIFICATION_FLAG) ? modName.data() : verifiedMods[modName.data()].dependencyPrefix;
- // Build archive distant URI
- std::string archiveName = std::format("{}-{}.zip", modPrefix, modVersion.data());
- std::string url = STORE_URL + archiveName;
+ std::string url = version.downloadLink;
+ std::string archiveName = fs::path(url).filename().generic_string();
spdlog::info(std::format("Fetching mod archive from {}", url));
// Download destination
@@ -390,7 +391,7 @@ int GetModArchiveSize(unzFile file, unz_global_info64 info)
return totalSize;
}
-void ModDownloader::ExtractMod(fs::path modPath)
+void ModDownloader::ExtractMod(fs::path modPath, VerifiedModPlatform platform)
{
unzFile file;
std::string name;
@@ -428,6 +429,14 @@ void ModDownloader::ExtractMod(fs::path modPath)
modState.total = GetModArchiveSize(file, gi);
modState.progress = 0;
+ // Right now, we only know how to extract Thunderstore mods
+ if (platform != VerifiedModPlatform::Thunderstore)
+ {
+ spdlog::error("Failed extracting mod from unknown platform (value: {}).", platform);
+ modState.state = UNKNOWN_PLATFORM;
+ return;
+ }
+
// Mod directory name (removing the ".zip" fom the archive name)
name = modPath.filename().string();
name = name.substr(0, name.length() - 4);
@@ -598,8 +607,9 @@ void ModDownloader::DownloadMod(std::string modName, std::string modVersion)
});
// Download mod archive
- std::string expectedHash = verifiedMods[modName].versions[modVersion].checksum;
- std::optional<fs::path> fetchingResult = FetchModFromDistantStore(std::string_view(modName), std::string_view(modVersion));
+ VerifiedModVersion fullVersion = verifiedMods[modName].versions[modVersion];
+ std::string expectedHash = fullVersion.checksum;
+ std::optional<fs::path> fetchingResult = FetchModFromDistantStore(std::string_view(modName), fullVersion);
if (!fetchingResult.has_value())
{
spdlog::error("Something went wrong while fetching archive, aborting.");
@@ -615,7 +625,7 @@ void ModDownloader::DownloadMod(std::string modName, std::string modVersion)
}
// Extract downloaded mod archive
- ExtractMod(archiveLocation);
+ ExtractMod(archiveLocation, fullVersion.platform);
});
requestThread.detach();
diff --git a/primedev/mods/autodownload/moddownloader.h b/primedev/mods/autodownload/moddownloader.h
index 98fc27ae..c7a88c19 100644
--- a/primedev/mods/autodownload/moddownloader.h
+++ b/primedev/mods/autodownload/moddownloader.h
@@ -5,17 +5,22 @@ class ModDownloader
private:
const char* VERIFICATION_FLAG = "-disablemodverification";
const char* CUSTOM_MODS_URL_FLAG = "-customverifiedurl=";
- const char* STORE_URL = "https://gcdn.thunderstore.io/live/repository/packages/";
const char* DEFAULT_MODS_LIST_URL = "https://raw.githubusercontent.com/R2Northstar/VerifiedMods/main/verified-mods.json";
char* modsListUrl;
+ enum class VerifiedModPlatform
+ {
+ Unknown,
+ Thunderstore
+ };
struct VerifiedModVersion
{
std::string checksum;
+ std::string downloadLink;
+ VerifiedModPlatform platform;
};
struct VerifiedModDetails
{
- std::string dependencyPrefix;
std::unordered_map<std::string, VerifiedModVersion> versions = {};
};
std::unordered_map<std::string, VerifiedModDetails> verifiedMods = {};
@@ -45,7 +50,7 @@ private:
* @param modVersion version of the mod to be downloaded
* @returns location of the downloaded archive
*/
- std::optional<fs::path> FetchModFromDistantStore(std::string_view modName, std::string_view modVersion);
+ std::optional<fs::path> FetchModFromDistantStore(std::string_view modName, VerifiedModVersion modVersion);
/**
* Tells if a mod archive has not been corrupted.
@@ -65,12 +70,13 @@ private:
* Extracts a mod archive to the game folder.
*
* This extracts a downloaded mod archive from its original location to the
- * current game profile, in the remote mods folder.
+ * current game profile; the install folder is defined by the platform parameter.
*
* @param modPath location of the downloaded archive
+ * @param platform origin of the downloaded archive
* @returns nothing
*/
- void ExtractMod(fs::path modPath);
+ void ExtractMod(fs::path modPath, VerifiedModPlatform platform);
public:
ModDownloader();
@@ -131,7 +137,8 @@ public:
MOD_FETCHING_FAILED,
MOD_CORRUPTED, // Downloaded archive checksum does not match verified hash
NO_DISK_SPACE_AVAILABLE,
- NOT_FOUND // Mod is not currently being auto-downloaded
+ NOT_FOUND, // Mod is not currently being auto-downloaded
+ UNKNOWN_PLATFORM
};
struct MOD_STATE