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"
msgstr ""
msgid "Changes"
msgstr ""
msgid "No description."
msgstr ""
msgid "No changes."
msgstr ""
msgid "Code battle"
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"
msgstr "Změnit hráče\\Změnit hráče"
#, fuzzy
msgid "Changes"
msgstr "Hlavolamy"
msgid "Chapters:"
msgstr "Kapitoly:"
@ -988,6 +992,9 @@ msgstr "Další objekt\\Vybere následující objekt"
msgid "No"
msgstr "Ne"
msgid "No changes."
msgstr ""
#, fuzzy
msgid "No description."
msgstr "Rozlišení:"

View File

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

View File

@ -377,6 +377,10 @@ msgstr "Changement de caméra\\Autre de point de vue"
msgid "Change player\\Change player"
msgstr "Autre joueur\\Choix du nom du joueur"
#, fuzzy
msgid "Changes"
msgstr "Défis"
msgid "Chapters:"
msgstr "Liste des chapitres :"
@ -1006,6 +1010,9 @@ msgstr "Sélectionner l'objet suivant\\Sélectionner l'objet suivant"
msgid "No"
msgstr "Non"
msgid "No changes."
msgstr ""
#, fuzzy
msgid "No description."
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"
msgstr "Zmień gracza\\Zmień gracza"
msgid "Changes"
msgstr "Zmiany"
msgid "Chapters:"
msgstr "Rozdziały:"
@ -984,6 +987,9 @@ msgstr "Następny obiekt\\Zaznacza następny obiekt"
msgid "No"
msgstr "Nie"
msgid "No changes."
msgstr "Brak zmian."
msgid "No description."
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"
msgstr "Mudar jogador\\Mudar jogador"
#, fuzzy
msgid "Changes"
msgstr "Desafios"
msgid "Chapters:"
msgstr "Capítulos:"
@ -1001,6 +1005,9 @@ msgstr "Próximo objeto\\Selecionar o próximo objeto"
msgid "No"
msgstr "Não"
msgid "No changes."
msgstr ""
#, fuzzy
msgid "No description."
msgstr "Resolução:"

View File

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

View File

@ -67,7 +67,7 @@ void CModManager::Init()
}
// Search the folders for mods
const auto rawPaths = m_pathManager->FindMods();
auto rawPaths = m_pathManager->FindMods();
std::map<std::string, std::string> modPaths;
for (const auto& path : rawPaths)
{
@ -108,9 +108,9 @@ void CModManager::Init()
// Load the metadata for each mod
for (auto& mod : m_mods)
{
m_pathManager->AddMod(mod.path);
MountMod(mod, "/temp/mod");
LoadModData(mod);
m_pathManager->RemoveMod(mod.path);
UnmountMod(mod);
}
UpdatePaths();
@ -118,8 +118,8 @@ void CModManager::Init()
void CModManager::ReloadMods()
{
UnmountAllMods();
m_mods.clear();
m_pathManager->RemoveAllMods();
Init();
@ -165,12 +165,11 @@ size_t CModManager::MoveDown(size_t i)
void CModManager::UpdatePaths()
{
m_pathManager->RemoveAllMods();
for (const auto& mod : m_mods)
{
if (mod.enabled)
{
m_pathManager->AddMod(mod.path);
MountMod(mod);
}
}
}
@ -218,7 +217,7 @@ void CModManager::LoadModData(Mod& mod)
try
{
CLevelParser levelParser("manifest.txt");
CLevelParser levelParser("temp/mod/manifest.txt");
if (levelParser.Exists())
{
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());
}
// 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
#include <string>
#include <unordered_map>
#include <vector>
@ -32,6 +33,7 @@ struct ModData
std::string version{};
std::string website{};
std::string summary{};
std::vector<std::string> changes{};
};
struct Mod
@ -100,6 +102,10 @@ private:
//! Load mod data into mod
void LoadModData(Mod& mod);
void MountMod(const Mod& mod, const std::string& mountPoint = "");
void UnmountMod(const Mod& mod);
void UnmountAllMods();
private:
CApplication* m_app;
CPathManager* m_pathManager;

View File

@ -64,56 +64,6 @@ void CPathManager::SetSavePath(const std::string &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()
{
return m_dataPath;
@ -191,6 +141,44 @@ void CPathManager::InitPaths()
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> ret;

View File

@ -37,12 +37,6 @@ public:
void SetDataPath(const std::string &dataPath);
void SetLangPath(const std::string &langPath);
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& GetLangPath();
@ -53,8 +47,14 @@ public:
//! Loads configured paths
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:
//! Loads all mods from given directory
std::vector<std::string> FindModsInDir(const std::string &dir) const;
private:
@ -66,6 +66,6 @@ private:
std::string m_savePath;
//! Mod search paths
std::vector<std::string> m_modSearchDirs;
//! Mod paths
//! Additional mod paths
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());
return false;

View File

@ -36,7 +36,7 @@ public:
static std::string CleanPath(const std::string &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
static bool RemoveLocation(const std::string &location);
//! 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_VERSION_FIELD_NAME] = TR("Version");
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_CHANGES] = TR("No changes.");
stringsEvent[EVENT_LABEL_CODE_BATTLE] = TR("Code battle");

View File

@ -162,7 +162,9 @@ enum ResTextType
RT_MOD_AUTHOR_FIELD_NAME = 240,
RT_MOD_VERSION_FIELD_NAME = 241,
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
};

View File

@ -442,7 +442,26 @@ void CScreenModList::UpdateModDetails()
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->SetFirstLine(0);
}
void CScreenModList::UpdateModSummary()