aboutsummaryrefslogtreecommitdiff
path: root/libs/installer_fomod_plus/patchwizard/lib
diff options
context:
space:
mode:
Diffstat (limited to 'libs/installer_fomod_plus/patchwizard/lib')
-rw-r--r--libs/installer_fomod_plus/patchwizard/lib/PatchFinder.cpp86
-rw-r--r--libs/installer_fomod_plus/patchwizard/lib/PatchFinder.h49
2 files changed, 135 insertions, 0 deletions
diff --git a/libs/installer_fomod_plus/patchwizard/lib/PatchFinder.cpp b/libs/installer_fomod_plus/patchwizard/lib/PatchFinder.cpp
new file mode 100644
index 0000000..cd06b3a
--- /dev/null
+++ b/libs/installer_fomod_plus/patchwizard/lib/PatchFinder.cpp
@@ -0,0 +1,86 @@
+#include "PatchFinder.h"
+
+std::vector<AvailablePatch> PatchFinder::getAvailablePatchesForMod(const MOBase::IModInterface* mod)
+{
+ std::vector<AvailablePatch> available_patches = {};
+
+ // Verify that the mod has plugins in some shape or form.
+ if (const auto it = m_installedPlugins.find(mod); it == m_installedPlugins.end()) {
+ return available_patches;
+ }
+
+ // Look through the database
+ for (const auto& fomodDbEntries = mFomodDb->getEntries(); const auto& entry : fomodDbEntries) {
+ for (const auto& option : entry->getOptions()) {
+ // Skip options that are already selected/installed
+ if (option.selectionState == SelectionState::Selected) {
+ continue;
+ }
+
+ // Extract just the filename from the path (handle both / and \)
+ const auto fileName = option.fileName.substr(option.fileName.find_last_of("/\\") + 1);
+
+ // Skip if already installed in the modlist
+ if (m_installedPluginsCacheSet.contains(fileName)) {
+ continue;
+ }
+
+ // Technically without this check, we're doing a lookup for the entire modlist, which actually
+ // kinda works, but isn't the intention of this function. Might want to consider reworking
+ // it to map to mod names with one pass of the DB instead of a DB pass per mod.
+ if (!std::ranges::any_of(option.masters, [&mod](const std::string& master) {
+ return master == mod->name().toStdString();
+ })) {
+ continue;
+ }
+
+ // If we have all of this patch's masters in our modlist, and it's not installed, add it to the results.
+ if (std::ranges::all_of(option.masters, [this](const std::string& master) {
+ return m_installedPluginsCacheSet.contains(master);
+ })) {
+ AvailablePatch patch{
+ option,
+ entry->getDisplayName(),
+ mod->name().toStdString(),
+ false, // not installed
+ false, // not hidden
+ option.selectionState == SelectionState::Deselected // userDeselected
+ };
+ available_patches.push_back(patch);
+ }
+ }
+ }
+
+ return available_patches;
+}
+
+std::vector<AvailablePatch> PatchFinder::getAvailablePatchesForModList()
+{
+ std::vector<AvailablePatch> available_patches = {};
+ for (const auto& modName : m_organizer->modList()->allMods()) {
+ const auto mod = m_organizer->modList()->getMod(modName);
+ if (mod == nullptr) {
+ continue;
+ }
+ for (const auto& available_patch : getAvailablePatchesForMod(mod)) {
+ available_patches.emplace_back(available_patch);
+ }
+ }
+
+ return available_patches;
+}
+
+void PatchFinder::populateInstalledPlugins()
+{
+ for (const auto& modName : m_organizer->modList()->allMods()) {
+ const auto mod = m_organizer->modList()->getMod(modName);
+ const auto mod_tree = mod->fileTree();
+ for (auto it = mod_tree->begin(); it != mod_tree->end(); ++it) {
+ if ((*it)->isFile() && isPluginFile((*it)->name())) {
+ std::cout << "Plugin: " << (*it)->name().toStdString() << std::endl;
+ m_installedPlugins[mod].emplace_back((*it)->name().toStdString());
+ m_installedPluginsCacheSet.insert((*it)->name().toStdString());
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/libs/installer_fomod_plus/patchwizard/lib/PatchFinder.h b/libs/installer_fomod_plus/patchwizard/lib/PatchFinder.h
new file mode 100644
index 0000000..02327e3
--- /dev/null
+++ b/libs/installer_fomod_plus/patchwizard/lib/PatchFinder.h
@@ -0,0 +1,49 @@
+#pragma once
+
+#include "../../installer/lib/Logger.h"
+
+#include <FomodDB.h>
+#include <imodinterface.h>
+#include <imoinfo.h>
+#include <ifiletree.h>
+
+struct AvailablePatch {
+ FomodOption fomod_option;
+ std::string installer_name;
+ std::string patch_for_mod;
+ bool installed = false;
+ bool hidden = false;
+ bool userDeselected = false; // True if user explicitly chose not to install
+};
+
+class PatchFinder {
+friend class FomodPlusPatchWizard;
+
+public:
+ explicit PatchFinder(MOBase::IOrganizer* m_organizer) : m_organizer(m_organizer)
+ {
+ mFomodDb = std::make_unique<FomodDB>(m_organizer->basePath().toStdString());
+ logMessage(DEBUG, "mFomodDb loaded.");
+ }
+
+ std::vector<AvailablePatch> getAvailablePatchesForMod(const MOBase::IModInterface* mod);
+ std::vector<AvailablePatch> getAvailablePatchesForModList();
+
+protected:
+ void populateInstalledPlugins();
+
+private:
+ Logger& log = Logger::getInstance();
+ MOBase::IOrganizer* m_organizer;
+ std::unique_ptr<FomodDB> mFomodDb;
+
+ // Map of { pluginPtr: [1.esp, 2.esp, 3.esp] }
+ std::unordered_map<const MOBase::IModInterface*, std::vector<std::string> > m_installedPlugins;
+ std::unordered_set<std::string> m_installedPluginsCacheSet;
+
+ void logMessage(const LogLevel level, const std::string& message) const
+ {
+ log.logMessage(level, "[PATCHFINDER] " + message);
+ }
+
+}; \ No newline at end of file