Use optionals where appropriate

This commit is contained in:
Lars Mueller 2024-04-28 20:07:26 +02:00 committed by SFENCE
parent 90a070d94c
commit 4d73a56377
4 changed files with 44 additions and 37 deletions

View File

@ -224,20 +224,16 @@ void ModConfiguration::checkConflictsAndDeps()
void ModConfiguration::resolveDependencies()
{
// Step 1: Compile a list of the mod names we're working with
// Compile a list of the mod names we're working with
std::set<std::string> modnames;
ModSpec first_mod_spec;
ModSpec last_mod_spec;
bool have_first, have_last;
std::optional<ModSpec> first_mod_spec, last_mod_spec;
for (ModSpec &mod : m_unsatisfied_mods) {
if (mod.name == m_first_mod) {
if (m_first_mod.has_value() && mod.name == *m_first_mod) {
first_mod_spec = mod;
have_first = true;
} else if (mod.name == m_last_mod) {
} else if (m_last_mod.has_value() && mod.name == *m_last_mod) {
// only non optional depends have to be check for last mod
mod.unsatisfied_depends = mod.depends;
last_mod_spec = mod;
have_last = true;
} else {
modnames.insert(mod.name);
}
@ -252,13 +248,13 @@ void ModConfiguration::resolveDependencies()
);
}
// Step 2: Check first and last mod configuration
if (!m_first_mod.empty() && !have_first)
// Check for presence of first and last mod
if (m_first_mod.has_value() && !first_mod_spec.has_value())
throw ModError("The mod specified as first by the game was not found.");
if (!m_last_mod.empty() && !have_last)
if (m_last_mod.has_value() && !last_mod_spec.has_value())
throw ModError("The mod specified as last by the game was not found.");
// Step 3: get dependencies (including optional dependencies)
// Get dependencies (including optional dependencies)
// of each mod, split mods into satisfied and unsatisfied
std::vector<ModSpec> satisfied;
std::list<ModSpec> unsatisfied;
@ -269,7 +265,7 @@ void ModConfiguration::resolveDependencies()
if (modnames.count(optdep) != 0)
mod.unsatisfied_depends.insert(optdep);
}
if (have_last && mod.unsatisfied_depends.count(last_mod_spec.name) != 0) {
if (last_mod_spec.has_value() && mod.unsatisfied_depends.count(last_mod_spec->name) != 0) {
throw ModError("It is not allowed to have mod selected as last by the game in dependencies.");
}
// if a mod has no depends it is initially satisfied
@ -280,16 +276,16 @@ void ModConfiguration::resolveDependencies()
}
}
// Step 4: Check and add first mod
if (have_first) {
// Check and add first mod
if (first_mod_spec.has_value()) {
// dependencies are not allowed for first mod
if (!first_mod_spec.depends.empty() || !first_mod_spec.optdepends.empty())
if (!first_mod_spec->depends.empty() || !first_mod_spec->optdepends.empty())
throw ModError("Mod selected as first by the game is not allowed to have dependencies.");
satisfied.push_back(first_mod_spec);
satisfied.push_back(*first_mod_spec);
}
// Step 5: mods without unmet dependencies can be appended to
// Mods without unmet dependencies can be appended to
// the sorted list.
while (!satisfied.empty()) {
ModSpec mod = satisfied.back();
@ -305,19 +301,18 @@ void ModConfiguration::resolveDependencies()
++it;
}
}
if (have_last)
last_mod_spec.unsatisfied_depends.erase(mod.name);
if (last_mod_spec.has_value())
last_mod_spec->unsatisfied_depends.erase(mod.name);
}
// Step 6: write back list of unsatisfied mods
// Write back list of unsatisfied mods
m_unsatisfied_mods.assign(unsatisfied.begin(), unsatisfied.end());
// Step 7: Check and add first mod
if (have_last) {
// dependencies are not allowed for first mod
if (!last_mod_spec.unsatisfied_depends.empty())
// Check and add last mod
if (last_mod_spec.has_value()) {
if (!last_mod_spec->unsatisfied_depends.empty())
throw ModError("Mod selected as last by the game has an unsatisfied dependency.");
m_sorted_mods.push_back(last_mod_spec);
m_sorted_mods.push_back(*last_mod_spec);
}
}

View File

@ -20,6 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#pragma once
#include "mods.h"
#include <optional>
/**
@ -90,8 +91,8 @@ public:
void checkConflictsAndDeps();
private:
std::string m_first_mod;
std::string m_last_mod;
std::optional<std::string> m_first_mod;
std::optional<std::string> m_last_mod;
std::vector<ModSpec> m_sorted_mods;

View File

@ -170,13 +170,19 @@ SubgameSpec findSubgame(const std::string &id)
if (conf.exists("release"))
game_release = conf.getS32("release");
std::string first_mod;
if (conf.exists("first_mod"))
std::optional<std::string> first_mod;
if (conf.exists("first_mod")) {
first_mod = conf.get("first_mod");
if (first_mod->empty())
first_mod = std::nullopt;
}
std::string last_mod;
if (conf.exists("last_mod"))
std::optional<std::string> last_mod;
if (conf.exists("last_mod")) {
last_mod = conf.get("last_mod");
if (last_mod->empty())
last_mod = std::nullopt;
}
std::string menuicon_path;
#ifndef SERVER

View File

@ -23,6 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include <set>
#include <unordered_map>
#include <vector>
#include <optional>
class Settings;
@ -32,8 +33,8 @@ struct SubgameSpec
std::string title;
std::string author;
int release;
std::string first_mod;
std::string last_mod;
std::optional<std::string> first_mod;
std::optional<std::string> last_mod;
std::string path;
std::string gamemods_path;
@ -52,11 +53,15 @@ struct SubgameSpec
const std::string &title = "",
const std::string &menuicon_path = "",
const std::string &author = "", int release = 0,
const std::string &first_mod = "", const std::string &last_mod = "") :
const std::optional<std::string> &first_mod = std::nullopt,
const std::optional<std::string> &last_mod = std::nullopt) :
id(id),
title(title), author(author), release(release),
first_mod(first_mod), last_mod(last_mod), path(path),
gamemods_path(gamemods_path), addon_mods_paths(addon_mods_paths),
first_mod(first_mod),
last_mod(last_mod),
path(path),
gamemods_path(gamemods_path),
addon_mods_paths(addon_mods_paths),
menuicon_path(menuicon_path)
{
}