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
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
option(TESTS "Build tests" OFF)
@ -350,21 +353,19 @@ endif()
##
# Installation paths defined before compiling sources
if(PLATFORM_WINDOWS)
if(MXE)
# 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_LIB_DIR ./ CACHE STRING "Colobot libraries 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_DOC_DIR ./doc CACHE STRING "Colobot documentation directory")
else()
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_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_DOC_DIR ${CMAKE_INSTALL_PREFIX}/doc CACHE PATH "Colobot documentation directory")
endif()
if(PORTABLE OR (PLATFORM_WINDOWS AND MXE))
# 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_LIB_DIR ./ CACHE STRING "Colobot libraries 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_DOC_DIR ./doc CACHE STRING "Colobot documentation directory")
elseif(PLATFORM_WINDOWS)
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_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_DOC_DIR ${CMAKE_INSTALL_PREFIX}/doc CACHE PATH "Colobot documentation directory")
elseif(PLATFORM_MACOSX)
set(COLOBOT_INSTALL_BIN_DIR ../MacOS CACHE STRING "Colobot binary directory")
set(COLOBOT_INSTALL_LIB_DIR ../MacOS CACHE STRING "Colobot libraries directory")

View File

@ -38,46 +38,41 @@
#include <boost/filesystem.hpp>
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()
{
}
void CPathManager::SetDataPath(std::string dataPath)
void CPathManager::SetDataPath(const std::string &dataPath)
{
m_dataPath = dataPath;
}
void CPathManager::SetLangPath(std::string langPath)
void CPathManager::SetLangPath(const std::string &langPath)
{
m_langPath = langPath;
}
void CPathManager::SetSavePath(std::string savePath)
void CPathManager::SetSavePath(const std::string &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());
CResourceManager::AddLocation(modPath, true);
m_modAutoloadDir.push_back(modAutoloadDirPath);
}
void CPathManager::AddMod(const std::string &modPath)
{
m_mods.push_back(modPath);
}
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());
return std::string("Could not read from data directory:\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("'") + m_dataPath + std::string("'\n") +
std::string("Please check your installation, or supply a valid data directory by -datadir option.");
}
#if PLATFORM_WINDOWS
@ -133,19 +128,51 @@ std::string CPathManager::VerifyPaths()
void CPathManager::InitPaths()
{
LoadModsFromDir(m_dataPath+"/mods");
LoadModsFromDir(m_savePath+"/mods");
GetLogger()->Info("Data path: %s\n", m_dataPath.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::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
{
#if PLATFORM_WINDOWS
@ -156,9 +183,9 @@ void CPathManager::LoadModsFromDir(const std::string &dir)
for(; iterator != boost::filesystem::directory_iterator(); ++iterator)
{
#if PLATFORM_WINDOWS
AddMod(CSystemUtilsWindows::UTF8_Encode(iterator->path().wstring()));
ret.push_back(CSystemUtilsWindows::UTF8_Encode(iterator->path().wstring()));
#else
AddMod(iterator->path().string());
ret.push_back(iterator->path().string());
#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());
}
return ret;
}

View File

@ -17,16 +17,10 @@
* 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
#include "common/singleton.h"
#include <string>
#include <vector>
class CSystemUtils;
@ -34,16 +28,17 @@ class CSystemUtils;
* \class CPathManager
* \brief Class for managing data/lang/save paths
*/
class CPathManager : public CSingleton<CPathManager>
class CPathManager
{
public:
CPathManager(CSystemUtils* systemUtils);
~CPathManager();
void SetDataPath(std::string dataPath);
void SetLangPath(std::string langPath);
void SetSavePath(std::string savePath);
void AddMod(std::string modPath);
void SetDataPath(const std::string &dataPath);
void SetLangPath(const std::string &langPath);
void SetSavePath(const std::string &savePath);
void AddModAutoloadDir(const std::string &modAutoloadDirPath);
void AddMod(const std::string &modPath);
const std::string& GetDataPath();
const std::string& GetLangPath();
@ -56,14 +51,17 @@ public:
private:
//! Loads all mods from given directory
void LoadModsFromDir(const std::string &dir);
std::vector<std::string> FindModsInDir(const std::string &dir);
private:
CSystemUtils* m_systemUtils;
//! Data path
std::string m_dataPath;
//! Lang path
std::string m_langPath;
//! Save path
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 PORTABLE @PORTABLE@
#cmakedefine PORTABLE_SAVES @PORTABLE_SAVES@
#define COLOBOT_DEFAULT_DATADIR "@COLOBOT_INSTALL_DATA_DIR@"
#define COLOBOT_I18N_DIR "@COLOBOT_INSTALL_I18N_DIR@"

View File

@ -85,6 +85,16 @@ bool CResourceManager::RemoveLocation(const std::string &location)
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)
{

View File

@ -35,8 +35,12 @@ 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);
//! Remove a location from the search path
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 std::string GetSaveLocation();

View File

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

View File

@ -102,10 +102,15 @@ std::string CSystemUtilsMacOSX::GetLangPath()
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;
GetLogger()->Trace("Saved game files are going to %s\n", savegameDir.c_str());
return savegameDir;
#endif
}
void CSystemUtilsMacOSX::Usleep(int usec)

View File

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