From b6f1a18bebf18e9eeef3112356e40c1dd34c9ee4 Mon Sep 17 00:00:00 2001 From: Eduardo Bart Date: Sun, 21 Nov 2010 23:19:20 -0200 Subject: [PATCH] basic resource manager implementation load/save configurations files in user home --- src/configmanager.cpp | 21 +++++------ src/main.cpp | 21 +++++++++-- src/platform.h | 3 ++ src/resourcemanager.cpp | 82 +++++++++++++++++++++++++++++++++++++++++ src/resourcemanager.h | 32 +++++++++++++++- src/util.h | 1 + src/x11platform.cpp | 20 ++++++++-- 7 files changed, 160 insertions(+), 20 deletions(-) diff --git a/src/configmanager.cpp b/src/configmanager.cpp index 9cd683c3..061b205a 100644 --- a/src/configmanager.cpp +++ b/src/configmanager.cpp @@ -28,6 +28,7 @@ #include #include +#include "resourcemanager.h" ConfigManager g_config; @@ -43,11 +44,16 @@ ConfigManager::~ConfigManager() bool ConfigManager::load(const std::string& fileName) { - std::ifstream fin(fileName.c_str()); - if(!fin.good()) + m_fileName = fileName; + + if(!g_resources.fileExists(fileName)) return false; - m_fileName = fileName; + std::string fileContents = g_resources.loadTextFile(fileName); + if(fileContents.size() == 0) + return false; + + std::istringstream fin(fileContents); try { YAML::Parser parser(fin); @@ -71,16 +77,9 @@ bool ConfigManager::load(const std::string& fileName) void ConfigManager::save() { - std::ofstream fout(m_fileName.c_str()); - if(!fout.good()) { - error("Failed to save configuration file %s", m_fileName.c_str()); - return; - } - YAML::Emitter out; out << m_confsMap; - - fout << out.c_str(); + g_resources.saveFile(m_fileName, (const unsigned char*)out.c_str(), out.size()); } void ConfigManager::setValue(const std::string &key, const std::string &value) diff --git a/src/main.cpp b/src/main.cpp index e5d43c7a..e0be7bac 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -25,12 +25,13 @@ #include "engine.h" #include "const.h" #include "logger.h" +#include "configmanager.h" +#include "resourcemanager.h" +#include "platform.h" #include -#include "configmanager.h" -#include "util.h" -// catches terminate signals to exit nicely +/// Catches signals so we can exit nicely void signal_handler(int sig) { switch(sig) { @@ -48,7 +49,7 @@ void signal_handler(int sig) } } -/// Default otclient configurations +/// Default configurations void setDefaultConfigs() { g_config.setValue("width", 640); @@ -62,7 +63,15 @@ int main(int argc, const char *argv[]) signal(SIGINT, signal_handler); signal(SIGQUIT, signal_handler); + // setup resources + g_resources.init(argv[0]); + if(g_resources.setWriteDir(Platform::getAppUserDir())) + g_resources.addToSearchPath(Platform::getAppUserDir()); + + // before loading configurations set the default ones setDefaultConfigs(); + + // load configurations if(!g_config.load("config.yml")) notice("Could not read configuration file, default configurations will be used."); @@ -73,6 +82,10 @@ int main(int argc, const char *argv[]) g_engine.run(); g_engine.terminate(); + // save configurations before exiting g_config.save(); + + // unload resources + g_resources.terminate(); return 0; } diff --git a/src/platform.h b/src/platform.h index 73740f40..991421b9 100644 --- a/src/platform.h +++ b/src/platform.h @@ -63,6 +63,9 @@ namespace Platform void setVsync(bool enable = true); /// Swap GL buffers void swapBuffers(); + + /// Get the app user directory, the place to save files configurations files + const char *getAppUserDir(); } #endif // PLATFORM_H diff --git a/src/resourcemanager.cpp b/src/resourcemanager.cpp index 30006809..6de06568 100644 --- a/src/resourcemanager.cpp +++ b/src/resourcemanager.cpp @@ -23,6 +23,9 @@ #include "resourcemanager.h" +#include "logger.h" + +#include ResourceManager g_resources; @@ -35,3 +38,82 @@ ResourceManager::~ResourceManager() { } + +void ResourceManager::init(const char *argv0) +{ + PHYSFS_init(argv0); +} + +void ResourceManager::terminate() +{ + PHYSFS_deinit(); +} + +bool ResourceManager::setWriteDir(const std::string& path) +{ + bool ret = (bool)PHYSFS_setWriteDir(path.c_str()); + + if(!ret) + error("Could not set the path %s as write directory, file write will not work."); + return ret; +} + +bool ResourceManager::addToSearchPath(const std::string& path, bool insertInFront) +{ + if(!PHYSFS_addToSearchPath(path.c_str(), insertInFront ? 0 : 1)) { + error("Error while adding %s to resources search path: %s", PHYSFS_getLastError()); + return false; + } + return true; +} + +bool ResourceManager::fileExists(const std::string& filePath) +{ + return PHYSFS_exists(filePath.c_str()); +} + +unsigned char *ResourceManager::loadFile(const std::string& fileName, unsigned int *fileSize) +{ + PHYSFS_file *file = PHYSFS_openRead(fileName.c_str()); + if(!file) { + error("Failed to load file %s: %s", fileName.c_str(), PHYSFS_getLastError()); + *fileSize = 0; + return NULL; + } + + *fileSize = PHYSFS_fileLength(file); + unsigned char *buffer = new unsigned char[*fileSize]; + PHYSFS_read(file, (void*)buffer, 1, *fileSize); + PHYSFS_close(file); + return buffer; +} + +std::string ResourceManager::loadTextFile(const std::string& fileName) +{ + std::string text; + unsigned int fileSize; + char *buffer = (char *)loadFile(fileName, &fileSize); + if(buffer) { + text.assign(buffer); + delete[] buffer; + } + return text; +} + +bool ResourceManager::saveFile(const std::string &fileName, const unsigned char *data, unsigned int size) +{ + PHYSFS_file *file = PHYSFS_openWrite(fileName.c_str()); + if(!file) { + error("Failed to save file %s: %s", fileName.c_str(), PHYSFS_getLastError()); + return false; + } + + PHYSFS_write(file, (void*)data, size, 1); + PHYSFS_close(file); + return true; +} + +bool ResourceManager::saveTextFile(const std::string &fileName, std::string text) +{ + return saveFile(fileName, (const unsigned char*)text.c_str(), text.size()); +} diff --git a/src/resourcemanager.h b/src/resourcemanager.h index fc84ebc8..34f90c74 100644 --- a/src/resourcemanager.h +++ b/src/resourcemanager.h @@ -26,7 +26,6 @@ #define RESOURCEMANAGER_H #include -#include class ResourceManager { @@ -34,7 +33,36 @@ public: ResourceManager(); ~ResourceManager(); -private: + void init(const char *argv0); + void terminate(); + + /// Sets the write directory + bool setWriteDir(const std::string &path); + + /// Adds a directory or zip archive to the search path + bool addToSearchPath(const std::string& path, bool insertInFront = true); + + /// Checks whether the given file exists in the search path + bool fileExists(const std::string& filePath); + + /// Searches for zip files and adds them to the search path + void searchAndAddArchives(const std::string &path, + const std::string &ext, + const bool append); + + /** Load a file by allocating a buffer and filling it with the file contents + * where fileSize will be set to the file size. + * The returned buffer must be freed with delete[]. */ + unsigned char *loadFile(const std::string &fileName, unsigned int *fileSize); + + /// Loads a text file into a std::string + std::string loadTextFile(const std::string &fileName); + + /// Save a file into write directory + bool saveFile(const std::string &fileName, const unsigned char *data, unsigned int size); + + /// Save a text file into write directory + bool saveTextFile(const std::string &fileName, std::string text); }; extern ResourceManager g_resources; diff --git a/src/util.h b/src/util.h index 967ec7b0..27256151 100644 --- a/src/util.h +++ b/src/util.h @@ -43,6 +43,7 @@ inline std::string castToString(const T& x) { return ss.str(); } +/// Convert std:;string to int/float like types template inline T castFromString(const std::string& s) { std::istringstream ss(s); diff --git a/src/x11platform.cpp b/src/x11platform.cpp index 6c1c2252..2262f6a7 100644 --- a/src/x11platform.cpp +++ b/src/x11platform.cpp @@ -26,18 +26,23 @@ #include "engine.h" #include "input.h" #include "logger.h" +#include "const.h" -#include +#include +#include +#include +#include +#include #include +#include #include #include -#include -#include #include #include #include +#include struct X11PlatformPrivate { Display *display; @@ -719,3 +724,12 @@ int Platform::getWindowHeight() { return x11.height; } + +const char *Platform::getAppUserDir() +{ + std::stringstream sdir; + sdir << PHYSFS_getUserDir() << "/." << APP_NAME << "/"; + if((mkdir(sdir.str().c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0) && (errno != EEXIST)) + error("Couldn't create directory for saving configuration file. (%s)", sdir.str().c_str()); + return sdir.str().c_str(); +}