Add saving mods list in colobot.ini

pyro-refactor
MrSimbax 2020-07-19 15:02:35 +02:00
parent 69d2d39c36
commit 63bf6bed08
6 changed files with 118 additions and 28 deletions

View File

@ -520,7 +520,9 @@ bool CApplication::Create()
GetLogger()->Warn("Config could not be loaded. Default values will be used!\n"); GetLogger()->Warn("Config could not be loaded. Default values will be used!\n");
} }
m_modManager->ReinitMods(); m_modManager->FindMods();
m_modManager->SaveMods();
m_modManager->UpdatePaths();
// Create the sound instance. // Create the sound instance.
#ifdef OPENAL_SOUND #ifdef OPENAL_SOUND

View File

@ -19,22 +19,18 @@
#include "app/modman.h" #include "app/modman.h"
//TODO: clean up includes
#include "common/config.h" #include "common/config.h"
#include "app/app.h" #include "app/app.h"
#include "app/pathman.h" #include "app/pathman.h"
#include "common/config_file.h"
#include "common/logger.h" #include "common/logger.h"
#include "common/restext.h"
#include "common/settings.h"
#include "common/stringutils.h"
#include "common/resources/resourcemanager.h" #include "common/resources/resourcemanager.h"
#include "common/system/system.h"
#include <algorithm> #include <algorithm>
#include <set>
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
@ -46,16 +42,64 @@ CModManager::CModManager(CApplication* app, CPathManager* pathManager)
{ {
} }
void CModManager::ReinitMods() void CModManager::FindMods()
{ {
m_mods.clear(); m_mods.clear();
const auto foundMods = m_pathManager->FindMods();
for (const auto& modPath : foundMods) // Load names from the config file
std::vector<std::string> savedModNames;
GetConfigFile().GetArrayProperty("Mods", "Names", savedModNames);
std::vector<bool> savedEnabled;
GetConfigFile().GetArrayProperty("Mods", "Enabled", savedEnabled);
// Transform the data into Mod structures
m_mods.reserve(savedModNames.size());
for (int i = 0; i < savedModNames.size(); ++i)
{ {
Mod mod; Mod mod{};
mod.name = boost::filesystem::path(modPath).stem().string(); mod.name = savedModNames[i];
mod.path = modPath; if (i < savedEnabled.size())
mod.enabled = m_pathManager->ModLoaded(mod.path); //TODO: load from some config file {
mod.enabled = savedEnabled[i];
}
mod.path = ""; // Find the path later
m_mods.push_back(mod);
}
// Search the folders for mods
const auto rawPaths = m_pathManager->FindMods();
std::map<std::string, std::string> modPaths;
for (const auto& path : rawPaths)
{
auto modName = boost::filesystem::path(path).stem().string();
modPaths.insert(std::make_pair(modName, path));
}
// Find paths for already saved mods
auto it = m_mods.begin();
while (it != m_mods.end())
{
auto& mod = *it;
const auto pathsIt = modPaths.find(mod.name);
if (pathsIt != modPaths.end())
{
mod.path = (*pathsIt).second;
modPaths.erase(pathsIt);
++it;
}
else
{
GetLogger()->Warn("Could not find mod %s, removing it from the list\n", mod.name.c_str());
it = m_mods.erase(it);
}
}
// Add the remaining found mods to the end of the list
for (const auto& newMod : modPaths)
{
Mod mod{};
mod.name = newMod.first;
mod.path = newMod.second;
m_mods.push_back(mod); m_mods.push_back(mod);
} }
} }
@ -82,23 +126,38 @@ void CModManager::DisableMod(const std::string& modName)
mod->enabled = false; mod->enabled = false;
} }
void CModManager::ReloadMods() void CModManager::UpdatePaths()
{ {
m_pathManager->RemoveAllMods();
for (const auto& mod : m_mods) for (const auto& mod : m_mods)
{ {
bool loaded = m_pathManager->ModLoaded(mod.path); if (mod.enabled)
if (mod.enabled && !loaded)
{ {
m_pathManager->AddMod(mod.path); m_pathManager->AddMod(mod.path);
} }
else if (!mod.enabled && loaded)
{
m_pathManager->RemoveMod(mod.path);
}
} }
}
void CModManager::ReloadResources()
{
m_app->ReloadResources(); m_app->ReloadResources();
} }
void CModManager::SaveMods()
{
std::vector<std::string> savedNames;
savedNames.reserve(m_mods.size());
std::transform(m_mods.begin(), m_mods.end(), std::back_inserter(savedNames), [](const Mod& mod) { return mod.name; });
GetConfigFile().SetArrayProperty("Mods", "Names", savedNames);
std::vector<bool> savedEnabled;
savedEnabled.reserve(m_mods.size());
std::transform(m_mods.begin(), m_mods.end(), std::back_inserter(savedEnabled), [](const Mod& mod) { return mod.enabled; });
GetConfigFile().SetArrayProperty("Mods", "Enabled", savedEnabled);
GetConfigFile().Save();
}
boost::optional<Mod> CModManager::GetMod(const std::string& modName) boost::optional<Mod> CModManager::GetMod(const std::string& modName)
{ {
Mod* mod = FindMod(modName); Mod* mod = FindMod(modName);

View File

@ -30,8 +30,8 @@ class CPathManager;
struct Mod struct Mod
{ {
std::string name; std::string name{};
std::string path; std::string path{};
bool enabled = false; bool enabled = false;
//TODO: add metadata for UI //TODO: add metadata for UI
}; };
@ -41,6 +41,7 @@ struct Mod
* \brief Main application * \brief Main application
* *
* This class handles the list of currently loaded mods. * This class handles the list of currently loaded mods.
* The order matters since the order in which files are loaded matters.
* *
*/ */
class CModManager class CModManager
@ -49,7 +50,7 @@ public:
CModManager(CApplication* app, CPathManager* pathManager); CModManager(CApplication* app, CPathManager* pathManager);
//! Finds all the mods along with their metadata //! Finds all the mods along with their metadata
void ReinitMods(); void FindMods();
//! Removes a mod from the list of loaded mods //! Removes a mod from the list of loaded mods
void EnableMod(const std::string& modName); void EnableMod(const std::string& modName);
@ -58,7 +59,13 @@ public:
void DisableMod(const std::string& modName); void DisableMod(const std::string& modName);
//! Reloads application resources so the enabled mods are applied //! Reloads application resources so the enabled mods are applied
void ReloadMods(); void ReloadResources();
//! Saves the current configuration of mods to the config file
void SaveMods();
//! Updates the paths in Path Manager according to the current mod configuration
void UpdatePaths();
boost::optional<Mod> GetMod(const std::string& modName); boost::optional<Mod> GetMod(const std::string& modName);
const std::vector<Mod>& GetMods() const; const std::vector<Mod>& GetMods() const;

View File

@ -73,17 +73,30 @@ void CPathManager::AddMod(const std::string &modPath)
{ {
GetLogger()->Info("Loading mod: '%s'\n", modPath.c_str()); GetLogger()->Info("Loading mod: '%s'\n", modPath.c_str());
CResourceManager::AddLocation(modPath, true); CResourceManager::AddLocation(modPath, true);
m_mods.push_back(modPath);
} }
void CPathManager::RemoveMod(const std::string &modPath) void CPathManager::RemoveMod(const std::string &modPath)
{ {
GetLogger()->Info("Unloading mod: '%s'\n", modPath.c_str()); GetLogger()->Info("Unloading mod: '%s'\n", modPath.c_str());
CResourceManager::RemoveLocation(modPath); CResourceManager::RemoveLocation(modPath);
auto it = std::find(m_mods.cbegin(), m_mods.cend(), modPath);
if (it != m_mods.cend())
m_mods.erase(it);
}
void CPathManager::RemoveAllMods()
{
for (const auto& modPath : m_mods)
{
CResourceManager::RemoveLocation(modPath);
}
m_mods.clear();
} }
bool CPathManager::ModLoaded(const std::string& modPath) bool CPathManager::ModLoaded(const std::string& modPath)
{ {
return CResourceManager::LocationExists(modPath); return std::find(m_mods.cbegin(), m_mods.cend(), modPath) != m_mods.end();
} }
std::vector<std::string> CPathManager::FindMods() const std::vector<std::string> CPathManager::FindMods() const

View File

@ -40,6 +40,7 @@ public:
void AddModSearchDir(const std::string &modSearchDirPath); void AddModSearchDir(const std::string &modSearchDirPath);
void AddMod(const std::string &modPath); void AddMod(const std::string &modPath);
void RemoveMod(const std::string &modPath); void RemoveMod(const std::string &modPath);
void RemoveAllMods();
bool ModLoaded(const std::string& modPath); bool ModLoaded(const std::string& modPath);
std::vector<std::string> FindMods() const; std::vector<std::string> FindMods() const;
@ -65,4 +66,6 @@ private:
std::string m_savePath; std::string m_savePath;
//! Mod search paths //! Mod search paths
std::vector<std::string> m_modSearchDirs; std::vector<std::string> m_modSearchDirs;
//! Mod paths
std::vector<std::string> m_mods;
}; };

View File

@ -71,6 +71,8 @@ void CScreenSetupMods::CreateInterface()
Math::Point pos, ddim; Math::Point pos, ddim;
std::string name; std::string name;
m_modManager->FindMods();
CScreenSetup::CreateInterface(); CScreenSetup::CreateInterface();
pw = static_cast<CWindow*>(m_interface->SearchControl(EVENT_WINDOW5)); pw = static_cast<CWindow*>(m_interface->SearchControl(EVENT_WINDOW5));
if ( pw == nullptr ) return; if ( pw == nullptr ) return;
@ -155,7 +157,9 @@ bool CScreenSetupMods::EventProcess(const Event &event)
modName = pl->GetItemName(pl->GetSelect()); modName = pl->GetItemName(pl->GetSelect());
m_modManager->EnableMod(modName); m_modManager->EnableMod(modName);
m_modManager->ReloadMods(); m_modManager->SaveMods();
m_modManager->UpdatePaths();
m_modManager->ReloadResources();
m_main->ChangePhase(PHASE_SETUPm); m_main->ChangePhase(PHASE_SETUPm);
break; break;
@ -166,7 +170,9 @@ bool CScreenSetupMods::EventProcess(const Event &event)
modName = pl->GetItemName(pl->GetSelect()); modName = pl->GetItemName(pl->GetSelect());
m_modManager->DisableMod(modName); m_modManager->DisableMod(modName);
m_modManager->ReloadMods(); m_modManager->SaveMods();
m_modManager->UpdatePaths();
m_modManager->ReloadResources();
m_main->ChangePhase(PHASE_SETUPm); m_main->ChangePhase(PHASE_SETUPm);
break; break;