Small CPathManager refactoring

1008-fix
krzys-h 2018-05-16 13:28:06 +02:00
parent c218fcce98
commit 073191d1ea
10 changed files with 120 additions and 64 deletions

View File

@ -201,6 +201,9 @@ option(OFFICIAL_BUILD "Official build (changes crash screen text)" OFF)
# Portable build - load all data from current directory # Portable build - load all data from current directory
option(PORTABLE "Portable build" OFF) option(PORTABLE "Portable build" OFF)
# Portable saves - suitable for e.g. putting the whole game on external storage and moving your saves with it
option(PORTABLE_SAVES "Portable saves" OFF)
# Building tests can be enabled/disabled # Building tests can be enabled/disabled
option(TESTS "Build tests" OFF) option(TESTS "Build tests" OFF)
@ -350,21 +353,19 @@ endif()
## ##
# Installation paths defined before compiling sources # Installation paths defined before compiling sources
if(PLATFORM_WINDOWS) if(PORTABLE OR (PLATFORM_WINDOWS AND MXE))
if(MXE) # We need to use STRING because PATH doesn't accept relative paths
# We need to use STRING because PATH doesn't accept relative paths set(COLOBOT_INSTALL_BIN_DIR ./ CACHE STRING "Colobot binary directory")
set(COLOBOT_INSTALL_BIN_DIR ./ CACHE STRING "Colobot binary directory") set(COLOBOT_INSTALL_LIB_DIR ./ CACHE STRING "Colobot libraries directory")
set(COLOBOT_INSTALL_LIB_DIR ./ CACHE STRING "Colobot libraries directory") set(COLOBOT_INSTALL_DATA_DIR ./data CACHE STRING "Colobot shared data directory")
set(COLOBOT_INSTALL_DATA_DIR ./data CACHE STRING "Colobot shared data directory") set(COLOBOT_INSTALL_I18N_DIR ./lang CACHE STRING "Colobot translations directory")
set(COLOBOT_INSTALL_I18N_DIR ./lang CACHE STRING "Colobot translations directory") set(COLOBOT_INSTALL_DOC_DIR ./doc CACHE STRING "Colobot documentation directory")
set(COLOBOT_INSTALL_DOC_DIR ./doc CACHE STRING "Colobot documentation directory") elseif(PLATFORM_WINDOWS)
else() set(COLOBOT_INSTALL_BIN_DIR ${CMAKE_INSTALL_PREFIX}/ CACHE PATH "Colobot binary directory")
set(COLOBOT_INSTALL_BIN_DIR ${CMAKE_INSTALL_PREFIX}/ CACHE PATH "Colobot binary directory") set(COLOBOT_INSTALL_LIB_DIR ${CMAKE_INSTALL_PREFIX}/ CACHE PATH "Colobot libraries directory")
set(COLOBOT_INSTALL_LIB_DIR ${CMAKE_INSTALL_PREFIX}/ CACHE PATH "Colobot libraries directory") set(COLOBOT_INSTALL_DATA_DIR ${CMAKE_INSTALL_PREFIX}/data CACHE PATH "Colobot shared data directory")
set(COLOBOT_INSTALL_DATA_DIR ${CMAKE_INSTALL_PREFIX}/data CACHE PATH "Colobot shared data directory") set(COLOBOT_INSTALL_I18N_DIR ${CMAKE_INSTALL_PREFIX}/lang CACHE PATH "Colobot translations directory")
set(COLOBOT_INSTALL_I18N_DIR ${CMAKE_INSTALL_PREFIX}/lang CACHE PATH "Colobot translations directory") set(COLOBOT_INSTALL_DOC_DIR ${CMAKE_INSTALL_PREFIX}/doc CACHE PATH "Colobot documentation directory")
set(COLOBOT_INSTALL_DOC_DIR ${CMAKE_INSTALL_PREFIX}/doc CACHE PATH "Colobot documentation directory")
endif()
elseif(PLATFORM_MACOSX) elseif(PLATFORM_MACOSX)
set(COLOBOT_INSTALL_BIN_DIR ../MacOS CACHE STRING "Colobot binary directory") set(COLOBOT_INSTALL_BIN_DIR ../MacOS CACHE STRING "Colobot binary directory")
set(COLOBOT_INSTALL_LIB_DIR ../MacOS CACHE STRING "Colobot libraries directory") set(COLOBOT_INSTALL_LIB_DIR ../MacOS CACHE STRING "Colobot libraries directory")

View File

@ -38,46 +38,41 @@
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
CPathManager::CPathManager(CSystemUtils* systemUtils) CPathManager::CPathManager(CSystemUtils* systemUtils)
: m_systemUtils(systemUtils) : m_dataPath(systemUtils->GetDataPath())
, m_langPath(systemUtils->GetLangPath())
, m_savePath(systemUtils->GetSaveDir())
, m_modAutoloadDir{ m_dataPath + "/mods", m_savePath + "/mods" }
, m_mods{}
{ {
#ifdef PORTABLE
m_dataPath = "./data";
m_langPath = "./lang";
m_savePath = "./saves";
#else
m_dataPath = m_systemUtils->GetDataPath();
m_langPath = m_systemUtils->GetLangPath();
#ifdef DEV_BUILD
m_savePath = "./saves";
#else
m_savePath = m_systemUtils->GetSaveDir();
#endif
#endif
} }
CPathManager::~CPathManager() CPathManager::~CPathManager()
{ {
} }
void CPathManager::SetDataPath(std::string dataPath) void CPathManager::SetDataPath(const std::string &dataPath)
{ {
m_dataPath = dataPath; m_dataPath = dataPath;
} }
void CPathManager::SetLangPath(std::string langPath) void CPathManager::SetLangPath(const std::string &langPath)
{ {
m_langPath = langPath; m_langPath = langPath;
} }
void CPathManager::SetSavePath(std::string savePath) void CPathManager::SetSavePath(const std::string &savePath)
{ {
m_savePath = savePath; m_savePath = savePath;
} }
void CPathManager::AddMod(std::string modPath) void CPathManager::AddModAutoloadDir(const std::string &modAutoloadDirPath)
{ {
GetLogger()->Info("Loading mod: '%s'\n", modPath.c_str()); m_modAutoloadDir.push_back(modAutoloadDirPath);
CResourceManager::AddLocation(modPath, true); }
void CPathManager::AddMod(const std::string &modPath)
{
m_mods.push_back(modPath);
} }
const std::string& CPathManager::GetDataPath() const std::string& CPathManager::GetDataPath()
@ -106,8 +101,8 @@ std::string CPathManager::VerifyPaths()
{ {
GetLogger()->Error("Data directory '%s' doesn't exist or is not a directory\n", m_dataPath.c_str()); GetLogger()->Error("Data directory '%s' doesn't exist or is not a directory\n", m_dataPath.c_str());
return std::string("Could not read from data directory:\n") + return std::string("Could not read from data directory:\n") +
std::string("'") + m_dataPath + std::string("'\n") + std::string("'") + m_dataPath + std::string("'\n") +
std::string("Please check your installation, or supply a valid data directory by -datadir option."); std::string("Please check your installation, or supply a valid data directory by -datadir option.");
} }
#if PLATFORM_WINDOWS #if PLATFORM_WINDOWS
@ -133,19 +128,51 @@ std::string CPathManager::VerifyPaths()
void CPathManager::InitPaths() void CPathManager::InitPaths()
{ {
LoadModsFromDir(m_dataPath+"/mods");
LoadModsFromDir(m_savePath+"/mods");
GetLogger()->Info("Data path: %s\n", m_dataPath.c_str()); GetLogger()->Info("Data path: %s\n", m_dataPath.c_str());
GetLogger()->Info("Save path: %s\n", m_savePath.c_str()); GetLogger()->Info("Save path: %s\n", m_savePath.c_str());
CResourceManager::AddLocation(m_dataPath, false); if (!m_modAutoloadDir.empty())
{
GetLogger()->Info("Mod autoload dirs:\n");
for(const std::string& modAutoloadDir : m_modAutoloadDir)
GetLogger()->Info(" * %s\n", modAutoloadDir.c_str());
}
if (!m_mods.empty())
{
GetLogger()->Info("Mods:\n");
for(const std::string& modPath : m_mods)
GetLogger()->Info(" * %s\n", modPath.c_str());
}
CResourceManager::AddLocation(m_dataPath);
for (const std::string& modAutoloadDir : m_modAutoloadDir)
{
GetLogger()->Trace("Searching for mods in '%s'...\n", modAutoloadDir.c_str());
for (const std::string& modPath : FindModsInDir(modAutoloadDir))
{
GetLogger()->Info("Autoloading mod: '%s'\n", modPath.c_str());
CResourceManager::AddLocation(modPath);
}
}
for (const std::string& modPath : m_mods)
{
GetLogger()->Info("Loading mod: '%s'\n", modPath.c_str());
CResourceManager::AddLocation(modPath);
}
CResourceManager::SetSaveLocation(m_savePath); CResourceManager::SetSaveLocation(m_savePath);
CResourceManager::AddLocation(m_savePath, true); CResourceManager::AddLocation(m_savePath);
GetLogger()->Debug("Finished initalizing data paths\n");
GetLogger()->Debug("PHYSFS search path is:\n");
for (const std::string& path : CResourceManager::GetLocations())
GetLogger()->Debug(" * %s\n", path.c_str());
} }
void CPathManager::LoadModsFromDir(const std::string &dir) std::vector<std::string> CPathManager::FindModsInDir(const std::string &dir)
{ {
GetLogger()->Trace("Looking for mods in '%s' ...\n", dir.c_str()); std::vector<std::string> ret;
try try
{ {
#if PLATFORM_WINDOWS #if PLATFORM_WINDOWS
@ -156,9 +183,9 @@ void CPathManager::LoadModsFromDir(const std::string &dir)
for(; iterator != boost::filesystem::directory_iterator(); ++iterator) for(; iterator != boost::filesystem::directory_iterator(); ++iterator)
{ {
#if PLATFORM_WINDOWS #if PLATFORM_WINDOWS
AddMod(CSystemUtilsWindows::UTF8_Encode(iterator->path().wstring())); ret.push_back(CSystemUtilsWindows::UTF8_Encode(iterator->path().wstring()));
#else #else
AddMod(iterator->path().string()); ret.push_back(iterator->path().string());
#endif #endif
} }
} }
@ -166,4 +193,5 @@ void CPathManager::LoadModsFromDir(const std::string &dir)
{ {
GetLogger()->Warn("Unable to load mods from directory '%s': %s\n", dir.c_str(), e.what()); GetLogger()->Warn("Unable to load mods from directory '%s': %s\n", dir.c_str(), e.what());
} }
return ret;
} }

View File

@ -17,16 +17,10 @@
* along with this program. If not, see http://gnu.org/licenses * along with this program. If not, see http://gnu.org/licenses
*/ */
/**
* \file app/pathman.h
* \brief Class for managing data/lang/save paths
*/
#pragma once #pragma once
#include "common/singleton.h"
#include <string> #include <string>
#include <vector>
class CSystemUtils; class CSystemUtils;
@ -34,16 +28,17 @@ class CSystemUtils;
* \class CPathManager * \class CPathManager
* \brief Class for managing data/lang/save paths * \brief Class for managing data/lang/save paths
*/ */
class CPathManager : public CSingleton<CPathManager> class CPathManager
{ {
public: public:
CPathManager(CSystemUtils* systemUtils); CPathManager(CSystemUtils* systemUtils);
~CPathManager(); ~CPathManager();
void SetDataPath(std::string dataPath); void SetDataPath(const std::string &dataPath);
void SetLangPath(std::string langPath); void SetLangPath(const std::string &langPath);
void SetSavePath(std::string savePath); void SetSavePath(const std::string &savePath);
void AddMod(std::string modPath); void AddModAutoloadDir(const std::string &modAutoloadDirPath);
void AddMod(const std::string &modPath);
const std::string& GetDataPath(); const std::string& GetDataPath();
const std::string& GetLangPath(); const std::string& GetLangPath();
@ -56,14 +51,17 @@ public:
private: private:
//! Loads all mods from given directory //! Loads all mods from given directory
void LoadModsFromDir(const std::string &dir); std::vector<std::string> FindModsInDir(const std::string &dir);
private: private:
CSystemUtils* m_systemUtils;
//! Data path //! Data path
std::string m_dataPath; std::string m_dataPath;
//! Lang path //! Lang path
std::string m_langPath; std::string m_langPath;
//! Save path //! Save path
std::string m_savePath; std::string m_savePath;
//! Mod autoload paths
std::vector<std::string> m_modAutoloadDir;
//! Mod paths
std::vector<std::string> m_mods;
}; };

View File

@ -16,7 +16,7 @@
#cmakedefine OPENAL_SOUND #cmakedefine OPENAL_SOUND
#cmakedefine PORTABLE @PORTABLE@ #cmakedefine PORTABLE_SAVES @PORTABLE_SAVES@
#define COLOBOT_DEFAULT_DATADIR "@COLOBOT_INSTALL_DATA_DIR@" #define COLOBOT_DEFAULT_DATADIR "@COLOBOT_INSTALL_DATA_DIR@"
#define COLOBOT_I18N_DIR "@COLOBOT_INSTALL_I18N_DIR@" #define COLOBOT_I18N_DIR "@COLOBOT_INSTALL_I18N_DIR@"

View File

@ -85,6 +85,16 @@ bool CResourceManager::RemoveLocation(const std::string &location)
return true; return true;
} }
std::vector<std::string> CResourceManager::GetLocations()
{
std::vector<std::string> ret;
char **list = PHYSFS_getSearchPath();
for (char **it = list; *it != nullptr; ++it)
ret.push_back(*it);
PHYSFS_freeList(list);
return ret;
}
bool CResourceManager::SetSaveLocation(const std::string &location) bool CResourceManager::SetSaveLocation(const std::string &location)
{ {

View File

@ -35,8 +35,12 @@ public:
static std::string CleanPath(const std::string &path); 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);
//! 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
static std::vector<std::string> GetLocations();
static bool SetSaveLocation(const std::string &location); static bool SetSaveLocation(const std::string &location);
static std::string GetSaveLocation(); static std::string GetSaveLocation();

View File

@ -190,5 +190,5 @@ std::string CSystemUtils::GetLangPath()
std::string CSystemUtils::GetSaveDir() std::string CSystemUtils::GetSaveDir()
{ {
return std::string("saves"); return "./saves";
} }

View File

@ -96,6 +96,9 @@ long long CSystemUtilsLinux::TimeStampExactDiff(SystemTimeStamp *before, SystemT
std::string CSystemUtilsLinux::GetSaveDir() std::string CSystemUtilsLinux::GetSaveDir()
{ {
#if PORTABLE_SAVES || DEV_BUILD
return CSystemUtils::GetSaveDir();
#else
std::string savegameDir; std::string savegameDir;
// Determine savegame dir according to XDG Base Directory Specification // Determine savegame dir according to XDG Base Directory Specification
@ -105,7 +108,8 @@ std::string CSystemUtilsLinux::GetSaveDir()
char *envHOME = getenv("HOME"); char *envHOME = getenv("HOME");
if (envHOME == nullptr) if (envHOME == nullptr)
{ {
savegameDir = "/tmp/colobot-save"; GetLogger()->Warn("Unable to find directory for saves - using current directory");
savegameDir = "./saves";
} }
else else
{ {
@ -119,6 +123,7 @@ std::string CSystemUtilsLinux::GetSaveDir()
GetLogger()->Trace("Saved game files are going to %s\n", savegameDir.c_str()); GetLogger()->Trace("Saved game files are going to %s\n", savegameDir.c_str());
return savegameDir; return savegameDir;
#endif
} }
void CSystemUtilsLinux::Usleep(int usec) void CSystemUtilsLinux::Usleep(int usec)

View File

@ -102,10 +102,15 @@ std::string CSystemUtilsMacOSX::GetLangPath()
std::string CSystemUtilsMacOSX::GetSaveDir() std::string CSystemUtilsMacOSX::GetSaveDir()
{ {
#if PORTABLE_SAVES || DEV_BUILD
// TODO: I have no idea if this actually works on Mac OS
return "./saves";
#else
std::string savegameDir = m_ASPath; std::string savegameDir = m_ASPath;
GetLogger()->Trace("Saved game files are going to %s\n", savegameDir.c_str()); GetLogger()->Trace("Saved game files are going to %s\n", savegameDir.c_str());
return savegameDir; return savegameDir;
#endif
} }
void CSystemUtilsMacOSX::Usleep(int usec) void CSystemUtilsMacOSX::Usleep(int usec)

View File

@ -110,12 +110,16 @@ std::wstring CSystemUtilsWindows::UTF8_Decode(const std::string& str)
std::string CSystemUtilsWindows::GetSaveDir() std::string CSystemUtilsWindows::GetSaveDir()
{ {
#if PORTABLE_SAVES || DEV_BUILD
return "./saves";
#else
std::string savegameDir; std::string savegameDir;
wchar_t* envUSERPROFILE = _wgetenv(L"USERPROFILE"); wchar_t* envUSERPROFILE = _wgetenv(L"USERPROFILE");
if (envUSERPROFILE == nullptr) if (envUSERPROFILE == nullptr)
{ {
savegameDir = "./saves"; GetLogger()->Warn("Unable to find directory for saves - using current directory");
savegameDir = CSystemUtils::GetSaveDir(false);
} }
else else
{ {
@ -124,6 +128,7 @@ std::string CSystemUtilsWindows::GetSaveDir()
GetLogger()->Trace("Saved game files are going to %s\n", savegameDir.c_str()); GetLogger()->Trace("Saved game files are going to %s\n", savegameDir.c_str());
return savegameDir; return savegameDir;
#endif
} }
void CSystemUtilsWindows::Usleep(int usec) void CSystemUtilsWindows::Usleep(int usec)