aboutsummaryrefslogtreecommitdiff
path: root/primedev
diff options
context:
space:
mode:
authorRémy Raes <raes.remy@gmail.com>2024-12-01 21:35:22 +0100
committerGitHub <noreply@github.com>2024-12-01 21:35:22 +0100
commit5e07df82e7bbd3296863995f688213e8639e8dcf (patch)
treeb9470f8a271fbcc0ab6863be4e8a49b037bfe774 /primedev
parent21843eeb83fd9c0057a05fbdfbbd76b6e969a9d1 (diff)
downloadNorthstarLauncher-main.tar.gz
NorthstarLauncher-main.zip
mods: Move collecting mods to own function (#830)HEADmain
Moves the logic that goes through all the paths where mods can be installed to its own function as part of improving code maintainability and future refactoring.
Diffstat (limited to 'primedev')
-rw-r--r--primedev/mods/modmanager.cpp213
-rw-r--r--primedev/mods/modmanager.h12
2 files changed, 122 insertions, 103 deletions
diff --git a/primedev/mods/modmanager.cpp b/primedev/mods/modmanager.cpp
index aa685c46..75bd4329 100644
--- a/primedev/mods/modmanager.cpp
+++ b/primedev/mods/modmanager.cpp
@@ -111,8 +111,6 @@ void ModManager::LoadMods()
if (m_bHasLoadedMods)
UnloadMods();
- std::vector<fs::path> modDirs;
-
// ensure dirs exist
fs::remove_all(GetCompiledAssetsPath());
fs::create_directories(GetModFolderPath());
@@ -137,107 +135,8 @@ void ModManager::LoadMods()
m_bHasEnabledModsCfg = m_EnabledModsCfg.IsObject();
}
- // get mod directories
- std::filesystem::directory_iterator classicModsDir = fs::directory_iterator(GetModFolderPath());
- std::filesystem::directory_iterator remoteModsDir = fs::directory_iterator(GetRemoteModFolderPath());
- std::filesystem::directory_iterator thunderstoreModsDir = fs::directory_iterator(GetThunderstoreModFolderPath());
-
- for (fs::directory_entry dir : classicModsDir)
- if (fs::exists(dir.path() / "mod.json"))
- modDirs.push_back(dir.path());
-
- // Special case for Thunderstore and remote mods directories
- // Set up regex for `AUTHOR-MOD-VERSION` pattern
- std::regex pattern(R"(.*\\([a-zA-Z0-9_]+)-([a-zA-Z0-9_]+)-(\d+\.\d+\.\d+))");
-
- for (fs::directory_iterator dirIterator : {thunderstoreModsDir, remoteModsDir})
- {
- for (fs::directory_entry dir : dirIterator)
- {
- fs::path modsDir = dir.path() / "mods"; // Check for mods folder in the Thunderstore mod
- // Use regex to match `AUTHOR-MOD-VERSION` pattern
- if (!std::regex_match(dir.path().string(), pattern))
- {
- spdlog::warn("The following directory did not match 'AUTHOR-MOD-VERSION': {}", dir.path().string());
- continue; // skip loading mod that doesn't match
- }
- if (fs::exists(modsDir) && fs::is_directory(modsDir))
- {
- for (fs::directory_entry subDir : fs::directory_iterator(modsDir))
- {
- if (fs::exists(subDir.path() / "mod.json"))
- {
- modDirs.push_back(subDir.path());
- }
- }
- }
- }
- }
-
- for (fs::path modDir : modDirs)
- {
- // read mod json file
- std::ifstream jsonStream(modDir / "mod.json");
- std::stringstream jsonStringStream;
-
- // fail if no mod json
- if (jsonStream.fail())
- {
- spdlog::warn(
- "Mod file at '{}' does not exist or could not be read, is it installed correctly?", (modDir / "mod.json").string());
- continue;
- }
-
- while (jsonStream.peek() != EOF)
- jsonStringStream << (char)jsonStream.get();
-
- jsonStream.close();
-
- Mod mod(modDir, (char*)jsonStringStream.str().c_str());
-
- for (auto& pair : mod.DependencyConstants)
- {
- if (m_DependencyConstants.find(pair.first) != m_DependencyConstants.end() && m_DependencyConstants[pair.first] != pair.second)
- {
- spdlog::error(
- "'{}' attempted to register a dependency constant '{}' for '{}' that already exists for '{}'. "
- "Change the constant name.",
- mod.Name,
- pair.first,
- pair.second,
- m_DependencyConstants[pair.first]);
- mod.m_bWasReadSuccessfully = false;
- break;
- }
- if (m_DependencyConstants.find(pair.first) == m_DependencyConstants.end())
- m_DependencyConstants.emplace(pair);
- }
-
- for (std::string& dependency : mod.PluginDependencyConstants)
- {
- m_PluginDependencyConstants.insert(dependency);
- }
-
- if (m_bHasEnabledModsCfg && m_EnabledModsCfg.HasMember(mod.Name.c_str()))
- mod.m_bEnabled = m_EnabledModsCfg[mod.Name.c_str()].IsTrue();
- else
- mod.m_bEnabled = true;
-
- if (mod.m_bWasReadSuccessfully)
- {
- if (mod.m_bEnabled)
- spdlog::info("'{}' loaded successfully, version {}", mod.Name, mod.Version);
- else
- spdlog::info("'{}' loaded successfully, version {} (DISABLED)", mod.Name, mod.Version);
-
- m_LoadedMods.push_back(mod);
- }
- else
- spdlog::warn("Mod file at '{}' failed to load", (modDir / "mod.json").string());
- }
-
- // sort by load prio, lowest-highest
- std::sort(m_LoadedMods.begin(), m_LoadedMods.end(), [](Mod& a, Mod& b) { return a.LoadPriority < b.LoadPriority; });
+ // Load mod info from filesystem into `m_LoadedMods`
+ SearchFilesystemForMods();
// This is used to check if some mods have a folder but no entry in enabledmods.json
bool newModsDetected = false;
@@ -621,6 +520,114 @@ void ModManager::UnloadMods()
m_LoadedMods.clear();
}
+void ModManager::SearchFilesystemForMods()
+{
+ std::vector<fs::path> modDirs;
+ m_LoadedMods.clear();
+
+ // get mod directories
+ std::filesystem::directory_iterator classicModsDir = fs::directory_iterator(GetModFolderPath());
+ std::filesystem::directory_iterator remoteModsDir = fs::directory_iterator(GetRemoteModFolderPath());
+ std::filesystem::directory_iterator thunderstoreModsDir = fs::directory_iterator(GetThunderstoreModFolderPath());
+
+ for (fs::directory_entry dir : classicModsDir)
+ if (fs::exists(dir.path() / "mod.json"))
+ modDirs.push_back(dir.path());
+
+ // Special case for Thunderstore and remote mods directories
+ // Set up regex for `AUTHOR-MOD-VERSION` pattern
+ std::regex pattern(R"(.*\\([a-zA-Z0-9_]+)-([a-zA-Z0-9_]+)-(\d+\.\d+\.\d+))");
+
+ for (fs::directory_iterator dirIterator : {thunderstoreModsDir, remoteModsDir})
+ {
+ for (fs::directory_entry dir : dirIterator)
+ {
+ fs::path modsDir = dir.path() / "mods"; // Check for mods folder in the Thunderstore mod
+ // Use regex to match `AUTHOR-MOD-VERSION` pattern
+ if (!std::regex_match(dir.path().string(), pattern))
+ {
+ spdlog::warn("The following directory did not match 'AUTHOR-MOD-VERSION': {}", dir.path().string());
+ continue; // skip loading mod that doesn't match
+ }
+ if (fs::exists(modsDir) && fs::is_directory(modsDir))
+ {
+ for (fs::directory_entry subDir : fs::directory_iterator(modsDir))
+ {
+ if (fs::exists(subDir.path() / "mod.json"))
+ {
+ modDirs.push_back(subDir.path());
+ }
+ }
+ }
+ }
+ }
+
+ for (fs::path modDir : modDirs)
+ {
+ // read mod json file
+ std::ifstream jsonStream(modDir / "mod.json");
+ std::stringstream jsonStringStream;
+
+ // fail if no mod json
+ if (jsonStream.fail())
+ {
+ spdlog::warn(
+ "Mod file at '{}' does not exist or could not be read, is it installed correctly?", (modDir / "mod.json").string());
+ continue;
+ }
+
+ while (jsonStream.peek() != EOF)
+ jsonStringStream << (char)jsonStream.get();
+
+ jsonStream.close();
+
+ Mod mod(modDir, (char*)jsonStringStream.str().c_str());
+
+ for (auto& pair : mod.DependencyConstants)
+ {
+ if (m_DependencyConstants.find(pair.first) != m_DependencyConstants.end() && m_DependencyConstants[pair.first] != pair.second)
+ {
+ spdlog::error(
+ "'{}' attempted to register a dependency constant '{}' for '{}' that already exists for '{}'. "
+ "Change the constant name.",
+ mod.Name,
+ pair.first,
+ pair.second,
+ m_DependencyConstants[pair.first]);
+ mod.m_bWasReadSuccessfully = false;
+ break;
+ }
+ if (m_DependencyConstants.find(pair.first) == m_DependencyConstants.end())
+ m_DependencyConstants.emplace(pair);
+ }
+
+ for (std::string& dependency : mod.PluginDependencyConstants)
+ {
+ m_PluginDependencyConstants.insert(dependency);
+ }
+
+ if (m_bHasEnabledModsCfg && m_EnabledModsCfg.HasMember(mod.Name.c_str()))
+ mod.m_bEnabled = m_EnabledModsCfg[mod.Name.c_str()].IsTrue();
+ else
+ mod.m_bEnabled = true;
+
+ if (mod.m_bWasReadSuccessfully)
+ {
+ if (mod.m_bEnabled)
+ spdlog::info("'{}' loaded successfully, version {}", mod.Name, mod.Version);
+ else
+ spdlog::info("'{}' loaded successfully, version {} (DISABLED)", mod.Name, mod.Version);
+
+ m_LoadedMods.push_back(mod);
+ }
+ else
+ spdlog::warn("Mod file at '{}' failed to load", (modDir / "mod.json").string());
+ }
+
+ // sort by load prio, lowest-highest
+ std::sort(m_LoadedMods.begin(), m_LoadedMods.end(), [](Mod& a, Mod& b) { return a.LoadPriority < b.LoadPriority; });
+}
+
std::string ModManager::NormaliseModFilePath(const fs::path path)
{
std::string str = path.lexically_normal().string();
diff --git a/primedev/mods/modmanager.h b/primedev/mods/modmanager.h
index 6350a1fc..58ab319d 100644
--- a/primedev/mods/modmanager.h
+++ b/primedev/mods/modmanager.h
@@ -46,6 +46,18 @@ public:
std::unordered_map<std::string, std::string> m_DependencyConstants;
std::unordered_set<std::string> m_PluginDependencyConstants;
+private:
+ /**
+ * Load information for all mods from filesystem.
+ *
+ * This looks for mods in several directories (expecting them to be formatted in
+ * some way); it then uses respective `mod.json` manifest files to create `Mod`
+ * instances, which are then stored in the `m_LoadedMods` variable.
+ *
+ * @returns nothing
+ **/
+ void SearchFilesystemForMods();
+
public:
ModManager();
void LoadMods();