Add changes listing to mods

It's just listing directories of a mod for now, but should give some
idea what the mod changes.

Also moved some functionality from pathman to modman.

Mods added with the `-mod` parameter are now managed by modman.
pyro-refactor
MrSimbax 2020-07-23 17:44:38 +02:00
parent 16795e0d49
commit 51668c12d7
16 changed files with 158 additions and 69 deletions

View File

@ -327,9 +327,15 @@ msgstr ""
msgid "Website" msgid "Website"
msgstr "" msgstr ""
msgid "Changes"
msgstr ""
msgid "No description." msgid "No description."
msgstr "" msgstr ""
msgid "No changes."
msgstr ""
msgid "Code battle" msgid "Code battle"
msgstr "" msgstr ""

View File

@ -374,6 +374,10 @@ msgstr "Změnit kameru\\Přepíná mezi kamerou na robotu a za robotem"
msgid "Change player\\Change player" msgid "Change player\\Change player"
msgstr "Změnit hráče\\Změnit hráče" msgstr "Změnit hráče\\Změnit hráče"
#, fuzzy
msgid "Changes"
msgstr "Hlavolamy"
msgid "Chapters:" msgid "Chapters:"
msgstr "Kapitoly:" msgstr "Kapitoly:"
@ -988,6 +992,9 @@ msgstr "Další objekt\\Vybere následující objekt"
msgid "No" msgid "No"
msgstr "Ne" msgstr "Ne"
msgid "No changes."
msgstr ""
#, fuzzy #, fuzzy
msgid "No description." msgid "No description."
msgstr "Rozlišení:" msgstr "Rozlišení:"

View File

@ -375,6 +375,10 @@ msgstr "Andere Kamera\\Sichtpunkt einstellen"
msgid "Change player\\Change player" msgid "Change player\\Change player"
msgstr "Anderer Spieler\\Spielername ändern" msgstr "Anderer Spieler\\Spielername ändern"
#, fuzzy
msgid "Changes"
msgstr "Herausforderungen"
msgid "Chapters:" msgid "Chapters:"
msgstr "Liste der Kapitel:" msgstr "Liste der Kapitel:"
@ -1004,6 +1008,9 @@ msgstr "Nächstes auswählen\\Nächstes Objekt auswählen"
msgid "No" msgid "No"
msgstr "Nein" msgstr "Nein"
msgid "No changes."
msgstr ""
#, fuzzy #, fuzzy
msgid "No description." msgid "No description."
msgstr "Auflösung:" msgstr "Auflösung:"

View File

@ -377,6 +377,10 @@ msgstr "Changement de caméra\\Autre de point de vue"
msgid "Change player\\Change player" msgid "Change player\\Change player"
msgstr "Autre joueur\\Choix du nom du joueur" msgstr "Autre joueur\\Choix du nom du joueur"
#, fuzzy
msgid "Changes"
msgstr "Défis"
msgid "Chapters:" msgid "Chapters:"
msgstr "Liste des chapitres :" msgstr "Liste des chapitres :"
@ -1006,6 +1010,9 @@ msgstr "Sélectionner l'objet suivant\\Sélectionner l'objet suivant"
msgid "No" msgid "No"
msgstr "Non" msgstr "Non"
msgid "No changes."
msgstr ""
#, fuzzy #, fuzzy
msgid "No description." msgid "No description."
msgstr "Résolutions :" msgstr "Résolutions :"

View File

@ -373,6 +373,9 @@ msgstr "Zmień kamerę\\Przełącza pomiędzy kamerą pokładową i śledzącą"
msgid "Change player\\Change player" msgid "Change player\\Change player"
msgstr "Zmień gracza\\Zmień gracza" msgstr "Zmień gracza\\Zmień gracza"
msgid "Changes"
msgstr "Zmiany"
msgid "Chapters:" msgid "Chapters:"
msgstr "Rozdziały:" msgstr "Rozdziały:"
@ -984,6 +987,9 @@ msgstr "Następny obiekt\\Zaznacza następny obiekt"
msgid "No" msgid "No"
msgstr "Nie" msgstr "Nie"
msgid "No changes."
msgstr "Brak zmian."
msgid "No description." msgid "No description."
msgstr "Brak opisu." msgstr "Brak opisu."

View File

@ -371,6 +371,10 @@ msgstr "Mudar câmera\\Alterna entre câmera incorporada e câmera seguidora"
msgid "Change player\\Change player" msgid "Change player\\Change player"
msgstr "Mudar jogador\\Mudar jogador" msgstr "Mudar jogador\\Mudar jogador"
#, fuzzy
msgid "Changes"
msgstr "Desafios"
msgid "Chapters:" msgid "Chapters:"
msgstr "Capítulos:" msgstr "Capítulos:"
@ -1001,6 +1005,9 @@ msgstr "Próximo objeto\\Selecionar o próximo objeto"
msgid "No" msgid "No"
msgstr "Não" msgstr "Não"
msgid "No changes."
msgstr ""
#, fuzzy #, fuzzy
msgid "No description." msgid "No description."
msgstr "Resolução:" msgstr "Resolução:"

View File

@ -378,6 +378,10 @@ msgstr "Изменить вид\\Переключение между борто
msgid "Change player\\Change player" msgid "Change player\\Change player"
msgstr "Новый игрок\\Выберите имя для игрока" msgstr "Новый игрок\\Выберите имя для игрока"
#, fuzzy
msgid "Changes"
msgstr "Задания"
msgid "Chapters:" msgid "Chapters:"
msgstr "Разделы:" msgstr "Разделы:"
@ -1012,6 +1016,9 @@ msgstr "Следующий объект\\Выбор следующего объ
msgid "No" msgid "No"
msgstr "Нет" msgstr "Нет"
msgid "No changes."
msgstr ""
#, fuzzy #, fuzzy
msgid "No description." msgid "No description."
msgstr "Разрешение:" msgstr "Разрешение:"

View File

@ -67,7 +67,7 @@ void CModManager::Init()
} }
// Search the folders for mods // Search the folders for mods
const auto rawPaths = m_pathManager->FindMods(); auto rawPaths = m_pathManager->FindMods();
std::map<std::string, std::string> modPaths; std::map<std::string, std::string> modPaths;
for (const auto& path : rawPaths) for (const auto& path : rawPaths)
{ {
@ -108,9 +108,9 @@ void CModManager::Init()
// Load the metadata for each mod // Load the metadata for each mod
for (auto& mod : m_mods) for (auto& mod : m_mods)
{ {
m_pathManager->AddMod(mod.path); MountMod(mod, "/temp/mod");
LoadModData(mod); LoadModData(mod);
m_pathManager->RemoveMod(mod.path); UnmountMod(mod);
} }
UpdatePaths(); UpdatePaths();
@ -118,8 +118,8 @@ void CModManager::Init()
void CModManager::ReloadMods() void CModManager::ReloadMods()
{ {
UnmountAllMods();
m_mods.clear(); m_mods.clear();
m_pathManager->RemoveAllMods();
Init(); Init();
@ -165,12 +165,11 @@ size_t CModManager::MoveDown(size_t i)
void CModManager::UpdatePaths() void CModManager::UpdatePaths()
{ {
m_pathManager->RemoveAllMods();
for (const auto& mod : m_mods) for (const auto& mod : m_mods)
{ {
if (mod.enabled) if (mod.enabled)
{ {
m_pathManager->AddMod(mod.path); MountMod(mod);
} }
} }
} }
@ -218,7 +217,7 @@ void CModManager::LoadModData(Mod& mod)
try try
{ {
CLevelParser levelParser("manifest.txt"); CLevelParser levelParser("temp/mod/manifest.txt");
if (levelParser.Exists()) if (levelParser.Exists())
{ {
levelParser.Load(); levelParser.Load();
@ -279,4 +278,30 @@ void CModManager::LoadModData(Mod& mod)
{ {
GetLogger()->Warn("Failed parsing manifest for mod %s: %s\n", mod.name.c_str(), e.what()); GetLogger()->Warn("Failed parsing manifest for mod %s: %s\n", mod.name.c_str(), e.what());
} }
// Changes
data.changes = CResourceManager::ListDirectories("temp/mod");
}
void CModManager::MountMod(const Mod& mod, const std::string& mountPoint)
{
GetLogger()->Debug("Mounting mod: '%s' at path %s\n", mod.path.c_str(), mountPoint.c_str());
CResourceManager::AddLocation(mod.path, true, mountPoint);
}
void CModManager::UnmountMod(const Mod& mod)
{
if (CResourceManager::LocationExists(mod.path))
{
GetLogger()->Debug("Unmounting mod: '%s'\n", mod.path.c_str());
CResourceManager::RemoveLocation(mod.path);
}
}
void CModManager::UnmountAllMods()
{
for (const auto& mod : m_mods)
{
UnmountMod(mod);
}
} }

View File

@ -19,6 +19,7 @@
#pragma once #pragma once
#include <string>
#include <unordered_map> #include <unordered_map>
#include <vector> #include <vector>
@ -32,6 +33,7 @@ struct ModData
std::string version{}; std::string version{};
std::string website{}; std::string website{};
std::string summary{}; std::string summary{};
std::vector<std::string> changes{};
}; };
struct Mod struct Mod
@ -100,6 +102,10 @@ private:
//! Load mod data into mod //! Load mod data into mod
void LoadModData(Mod& mod); void LoadModData(Mod& mod);
void MountMod(const Mod& mod, const std::string& mountPoint = "");
void UnmountMod(const Mod& mod);
void UnmountAllMods();
private: private:
CApplication* m_app; CApplication* m_app;
CPathManager* m_pathManager; CPathManager* m_pathManager;

View File

@ -64,56 +64,6 @@ void CPathManager::SetSavePath(const std::string &savePath)
m_savePath = savePath; m_savePath = savePath;
} }
void CPathManager::AddModSearchDir(const std::string &modSearchDirPath)
{
m_modSearchDirs.push_back(modSearchDirPath);
}
void CPathManager::AddMod(const std::string &modPath)
{
GetLogger()->Debug("Adding mod: '%s'\n", modPath.c_str());
CResourceManager::AddLocation(modPath, true);
m_mods.push_back(modPath);
}
void CPathManager::RemoveMod(const std::string &modPath)
{
GetLogger()->Debug("Removing mod: '%s'\n", modPath.c_str());
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)
{
return std::find(m_mods.cbegin(), m_mods.cend(), modPath) != m_mods.end();
}
std::vector<std::string> CPathManager::FindMods() const
{
std::vector<std::string> mods;
GetLogger()->Info("Found mods:\n");
for (const auto &searchPath : m_modSearchDirs)
{
for (const auto &modPath : FindModsInDir(searchPath))
{
GetLogger()->Info(" * %s\n", modPath.c_str());
mods.push_back(modPath);
}
}
return mods;
}
const std::string& CPathManager::GetDataPath() const std::string& CPathManager::GetDataPath()
{ {
return m_dataPath; return m_dataPath;
@ -191,6 +141,44 @@ void CPathManager::InitPaths()
GetLogger()->Debug(" * %s\n", path.c_str()); GetLogger()->Debug(" * %s\n", path.c_str());
} }
void CPathManager::AddMod(const std::string &path)
{
m_mods.push_back(path);
}
std::vector<std::string> CPathManager::FindMods() const
{
std::vector<std::string> mods;
GetLogger()->Info("Found mods:\n");
for (const auto &searchPath : m_modSearchDirs)
{
for (const auto &modPath : FindModsInDir(searchPath))
{
GetLogger()->Info(" * %s\n", modPath.c_str());
mods.push_back(modPath);
}
}
GetLogger()->Info("Additional mod paths:\n");
for (const auto& modPath : m_mods)
{
if (boost::filesystem::exists(modPath))
{
GetLogger()->Info(" * %s\n", modPath.c_str());
mods.push_back(modPath);
}
else
{
GetLogger()->Warn("Mod does not exist: %s\n", modPath.c_str());
}
}
return mods;
}
void CPathManager::AddModSearchDir(const std::string &modSearchDirPath)
{
m_modSearchDirs.push_back(modSearchDirPath);
}
std::vector<std::string> CPathManager::FindModsInDir(const std::string &dir) const std::vector<std::string> CPathManager::FindModsInDir(const std::string &dir) const
{ {
std::vector<std::string> ret; std::vector<std::string> ret;

View File

@ -37,12 +37,6 @@ public:
void SetDataPath(const std::string &dataPath); void SetDataPath(const std::string &dataPath);
void SetLangPath(const std::string &langPath); void SetLangPath(const std::string &langPath);
void SetSavePath(const std::string &savePath); void SetSavePath(const std::string &savePath);
void AddModSearchDir(const std::string &modSearchDirPath);
void AddMod(const std::string &modPath);
void RemoveMod(const std::string &modPath);
void RemoveAllMods();
bool ModLoaded(const std::string& modPath);
std::vector<std::string> FindMods() const;
const std::string& GetDataPath(); const std::string& GetDataPath();
const std::string& GetLangPath(); const std::string& GetLangPath();
@ -53,8 +47,14 @@ public:
//! Loads configured paths //! Loads configured paths
void InitPaths(); void InitPaths();
//! Adds a path to a mod
void AddMod(const std::string& path);
//! Find paths to mods in mod search directories
std::vector<std::string> FindMods() const;
//! Adds a mod search directory
void AddModSearchDir(const std::string &modSearchDirPath);
private: private:
//! Loads all mods from given directory
std::vector<std::string> FindModsInDir(const std::string &dir) const; std::vector<std::string> FindModsInDir(const std::string &dir) const;
private: private:
@ -66,6 +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 //! Additional mod paths
std::vector<std::string> m_mods; std::vector<std::string> m_mods;
}; };

View File

@ -62,9 +62,9 @@ std::string CResourceManager::CleanPath(const std::string& path)
} }
bool CResourceManager::AddLocation(const std::string &location, bool prepend) bool CResourceManager::AddLocation(const std::string &location, bool prepend, const std::string &mountPoint)
{ {
if (!PHYSFS_mount(location.c_str(), nullptr, prepend ? 0 : 1)) if (!PHYSFS_mount(location.c_str(), mountPoint.c_str(), prepend ? 0 : 1))
{ {
GetLogger()->Error("Error while mounting \"%s\": %s\n", location.c_str(), PHYSFS_getLastError()); GetLogger()->Error("Error while mounting \"%s\": %s\n", location.c_str(), PHYSFS_getLastError());
return false; return false;

View File

@ -36,7 +36,7 @@ public:
static std::string CleanPath(const std::string &path); static std::string CleanPath(const std::string &path);
//! Add a location to the search path //! Add a location to the search path
static bool AddLocation(const std::string &location, bool prepend = true); static bool AddLocation(const std::string &location, bool prepend = true, const std::string &mountPoint = "");
//! Remove a location from the search path //! Remove a location from the search path
static bool RemoveLocation(const std::string &location); static bool RemoveLocation(const std::string &location);
//! List all locations in the search path //! List all locations in the search path

View File

@ -168,7 +168,9 @@ void InitializeRestext()
stringsText[RT_MOD_AUTHOR_FIELD_NAME] = TR("by"); stringsText[RT_MOD_AUTHOR_FIELD_NAME] = TR("by");
stringsText[RT_MOD_VERSION_FIELD_NAME] = TR("Version"); stringsText[RT_MOD_VERSION_FIELD_NAME] = TR("Version");
stringsText[RT_MOD_WEBSITE_FIELD_NAME] = TR("Website"); stringsText[RT_MOD_WEBSITE_FIELD_NAME] = TR("Website");
stringsText[RT_MOD_CHANGES_FIELD_NAME] = TR("Changes");
stringsText[RT_MOD_NO_SUMMARY] = TR("No description."); stringsText[RT_MOD_NO_SUMMARY] = TR("No description.");
stringsText[RT_MOD_NO_CHANGES] = TR("No changes.");
stringsEvent[EVENT_LABEL_CODE_BATTLE] = TR("Code battle"); stringsEvent[EVENT_LABEL_CODE_BATTLE] = TR("Code battle");

View File

@ -162,7 +162,9 @@ enum ResTextType
RT_MOD_AUTHOR_FIELD_NAME = 240, RT_MOD_AUTHOR_FIELD_NAME = 240,
RT_MOD_VERSION_FIELD_NAME = 241, RT_MOD_VERSION_FIELD_NAME = 241,
RT_MOD_WEBSITE_FIELD_NAME = 242, RT_MOD_WEBSITE_FIELD_NAME = 242,
RT_MOD_NO_SUMMARY = 243, RT_MOD_CHANGES_FIELD_NAME = 243,
RT_MOD_NO_SUMMARY = 244,
RT_MOD_NO_CHANGES = 245,
RT_MAX //! < number of values RT_MAX //! < number of values
}; };

View File

@ -442,7 +442,26 @@ void CScreenModList::UpdateModDetails()
details += "\\t;" + websiteFieldName + '\n' + data.website + '\n'; details += "\\t;" + websiteFieldName + '\n' + data.website + '\n';
} }
std::string changesFieldName;
GetResource(RES_TEXT, RT_MOD_CHANGES_FIELD_NAME, changesFieldName);
details += "\\t;" + changesFieldName + '\n';
if (!data.changes.empty())
{
for (const auto& change : data.changes)
{
details += change + '\n';
}
}
else
{
std::string noChanges;
GetResource(RES_TEXT, RT_MOD_NO_CHANGES, noChanges);
details += noChanges;
}
pe->SetText(details); pe->SetText(details);
pe->SetFirstLine(0);
} }
void CScreenModList::UpdateModSummary() void CScreenModList::UpdateModSummary()