diff --git a/client/CMT.cpp b/client/CMT.cpp index 7d2c4e793..8b47228f1 100644 --- a/client/CMT.cpp +++ b/client/CMT.cpp @@ -155,9 +155,9 @@ void init() static void prog_version(void) { printf("%s\n", GameConstants::VCMI_VERSION.c_str()); - printf(" data directory: %s\n", GameConstants::DATA_DIR.c_str()); - printf(" library directory: %s\n", GameConstants::LIB_DIR.c_str()); - printf(" binary directory: %s\n", GameConstants::BIN_DIR.c_str()); + printf(" data directory: %s\n", VCMIDirs::get().dataPath().c_str()); + printf(" library directory: %s\n", VCMIDirs::get().libraryPath().c_str()); + printf(" path to server: %s\n", VCMIDirs::get().serverPath().c_str()); } static void prog_help(const po::options_description &opts) @@ -195,7 +195,7 @@ int main(int argc, char** argv) OSX_checkForUpdates(); // Check that game data is prepared. Otherwise run vcmibuilder helper application - FILE* check = fopen((GVCMIDirs.UserPath + "/game_data_prepared").c_str(), "r"); + FILE* check = fopen((VCMIDirs::get().localPath() + "/game_data_prepared").c_str(), "r"); if (check == NULL) { system("open ./vcmibuilder.app"); return 0; @@ -253,7 +253,7 @@ int main(int argc, char** argv) CStopWatch total, pomtime; std::cout.flags(std::ios::unitbuf); - logfile = new std::ofstream((GVCMIDirs.UserPath + "/VCMI_Client_log.txt").c_str()); + logfile = new std::ofstream((VCMIDirs::get().localPath() + "/VCMI_Client_log.txt").c_str()); console = new CConsoleHandler; *console->cb = boost::bind(&processCommand, _1); console->start(); @@ -287,8 +287,8 @@ int main(int argc, char** argv) { tlog0 << "Fatal error: failed to load settings!\n"; tlog0 << "Possible reasons:\n"; - tlog0 << "\tCorrupted local configuration file at " << GVCMIDirs.UserPath << "/config/settings.json\n"; - tlog0 << "\tMissing or corrupted global configuration file at " << GameConstants::DATA_DIR << "/config/defaultSettings.json\n"; + tlog0 << "\tCorrupted local configuration file at " << VCMIDirs::get().localPath() << "/config/settings.json\n"; + tlog0 << "\tMissing or corrupted global configuration file at " << VCMIDirs::get().dataPath() << "/config/defaultSettings.json\n"; tlog0 << "VCMI will now exit...\n"; exit(EXIT_FAILURE); } diff --git a/client/CPlayerInterface.cpp b/client/CPlayerInterface.cpp index 8e8293a45..9ddca9d1f 100644 --- a/client/CPlayerInterface.cpp +++ b/client/CPlayerInterface.cpp @@ -1590,7 +1590,7 @@ int CPlayerInterface::getLastIndex( std::string namePrefix) using namespace boost::filesystem; using namespace boost::algorithm; - path gamesDir = GVCMIDirs.UserPath + "/Games"; + path gamesDir = VCMIDirs::get().localPath() + "/Games"; std::map dates; //save number => datestamp directory_iterator enddir; diff --git a/client/Client.cpp b/client/Client.cpp index 1e283e808..ce8f4efc1 100644 --- a/client/Client.cpp +++ b/client/Client.cpp @@ -763,8 +763,8 @@ CServerHandler::~CServerHandler() void CServerHandler::callServer() { setThreadName("CServerHandler::callServer"); - std::string logName = GVCMIDirs.UserPath + "/server_log.txt"; - std::string comm = GameConstants::BIN_DIR + GameConstants::PATH_SEPARATOR + GameConstants::SERVER_NAME + " " + port + " > " + logName; + std::string logName = VCMIDirs::get().localPath() + "/server_log.txt"; + std::string comm = VCMIDirs::get().serverPath() + " " + port + " > " + logName; int result = std::system(comm.c_str()); if (result == 0) tlog1 << "Server closed correctly\n"; diff --git a/lib/CArtHandler.cpp b/lib/CArtHandler.cpp index 31878eafc..de088993f 100644 --- a/lib/CArtHandler.cpp +++ b/lib/CArtHandler.cpp @@ -359,26 +359,20 @@ void CArtHandler::loadArtifactJson(CArtifact * art, const JsonNode & artifact) if (!artifact["components"].isNull()) { - art->constituents.reset(new std::vector()); + art->constituents.reset(new std::vector()); BOOST_FOREACH (auto component, artifact["components"].Vector()) { - VLC->modh->identifiers.requestIdentifier("artifact." + component.String(), [art](si32 id) + VLC->modh->identifiers.requestIdentifier("artifact." + component.String(), [=](si32 id) { // when this code is called both combinational art as well as component are loaded // so it is safe to access any of them - art->addConstituent(ArtifactID(id)); - VLC->arth->artifacts[id]->constituentOf.push_back(art->id); + art->constituents->push_back(VLC->arth->artifacts[id]); + VLC->arth->artifacts[id]->constituentOf.push_back(art); }); } } } -void CArtifact::addConstituent (ArtifactID component) -{ - assert (constituents); // not a combinational art - constituents->push_back (component); -} - ArtifactID CArtHandler::creatureToMachineID(CreatureID id) { int dif = 142; @@ -745,15 +739,14 @@ std::vector CArtifactInstance::assemblyPossibilities(const CA if(artType->constituents) //combined artifact already: no combining of combined artifacts... for now. return ret; - BOOST_FOREACH(ui32 possibleCombinedArt, artType->constituentOf) + BOOST_FOREACH(const CArtifact * artifact, artType->constituentOf) { - const CArtifact * const artifact = VLC->arth->artifacts[possibleCombinedArt]; assert(artifact->constituents); bool possible = true; - BOOST_FOREACH(ui32 constituentID, *artifact->constituents) //check if all constituents are available + BOOST_FOREACH(const CArtifact * constituent, *artifact->constituents) //check if all constituents are available { - if(!h->hasArt(constituentID, true)) //constituent must be equipped + if(!h->hasArt(constituent->id, true)) //constituent must be equipped { possible = false; break; @@ -876,15 +869,15 @@ void CCombinedArtifactInstance::createConstituents() assert(artType); assert(artType->constituents); - BOOST_FOREACH(ui32 a, *artType->constituents) + BOOST_FOREACH(const CArtifact * art, *artType->constituents) { - addAsConstituent(CArtifactInstance::createNewArtifactInstance(a), ArtifactPosition::PRE_FIRST); + addAsConstituent(CArtifactInstance::createNewArtifactInstance(art->id), ArtifactPosition::PRE_FIRST); } } void CCombinedArtifactInstance::addAsConstituent(CArtifactInstance *art, ArtifactPosition slot) { - assert(vstd::contains(*artType->constituents, art->artType->id)); + assert(vstd::contains(*artType->constituents, art->artType.get())); assert(art->getParentNodes().size() == 1 && art->getParentNodes().front() == art->artType); constituentsInfo.push_back(ConstituentInfo(art, slot)); attachTo(art); diff --git a/lib/CArtHandler.h b/lib/CArtHandler.h index 4b04d4fec..9273db159 100644 --- a/lib/CArtHandler.h +++ b/lib/CArtHandler.h @@ -57,7 +57,6 @@ public: const std::string &EventText() const; bool isBig () const; - void addConstituent (ArtifactID component); int getArtClassSerial() const; //0 - treasure, 1 - minor, 2 - major, 3 - relic, 4 - spell scroll, 5 - other std::string nodeName() const override; @@ -67,8 +66,8 @@ public: ui32 price; bmap > possibleSlots; //Bearer Type => ids of slots where artifact can be placed - std::unique_ptr > constituents; // Artifacts IDs a combined artifact consists of, or NULL. - std::vector constituentOf; // Reverse map of constituents - combined arts that include this art + std::unique_ptr > constituents; // Artifacts IDs a combined artifact consists of, or NULL. + std::vector constituentOf; // Reverse map of constituents - combined arts that include this art EartClass aClass; ArtifactID id; diff --git a/lib/CGameInterface.cpp b/lib/CGameInterface.cpp index 6467da820..f9281cde0 100644 --- a/lib/CGameInterface.cpp +++ b/lib/CGameInterface.cpp @@ -2,7 +2,7 @@ #include "CGameInterface.h" #include "BattleState.h" -#include "GameConstants.h" +#include "VCMIDirs.h" #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN //excludes rarely used stuff from windows headers - delete this line if something is missing @@ -72,26 +72,12 @@ rett * createAny(std::string dllname, std::string methodName) return ret; } -//Currently AI libraries use "lib" prefix only on non-win systems. -//May be applied to Win systems as well to remove this ifdef -#ifdef _WIN32 -std::string getAIFileName(std::string input) -{ - return input + '.' + GameConstants::LIB_EXT; -} -#else -std::string getAIFileName(std::string input) -{ - return "lib" + input + '.' + GameConstants::LIB_EXT; -} -#endif - template rett * createAnyAI(std::string dllname, std::string methodName) { tlog1<<"Opening "<(GameConstants::LIB_DIR + "/AI/" + filename, methodName); + std::string filename = VCMIDirs::get().libraryName(dllname); + rett* ret = createAny(VCMIDirs::get().libraryPath() + "/AI/" + filename, methodName); ret->dllName = dllname; return ret; } diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index fec9426dc..890766fdf 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -52,6 +52,7 @@ set(lib_SRCS ResourceSet.cpp RegisterTypes.cpp VCMI_Lib.cpp + VCMIDirs.cpp ) set(lib_HEADERS diff --git a/lib/Filesystem/CResourceLoader.cpp b/lib/Filesystem/CResourceLoader.cpp index b74ce9c3d..15bc805ce 100644 --- a/lib/Filesystem/CResourceLoader.cpp +++ b/lib/Filesystem/CResourceLoader.cpp @@ -321,16 +321,16 @@ void CResourceHandler::initialize() initialLoader = new CResourceLoader; resourceLoader = new CResourceLoader; - shared_ptr rootDir(new CFilesystemLoader(GameConstants::DATA_DIR, 0, true)); + shared_ptr rootDir(new CFilesystemLoader(VCMIDirs::get().dataPath(), 0, true)); initialLoader->addLoader("GLOBAL/", rootDir, false); initialLoader->addLoader("ALL/", rootDir, false); auto userDir = rootDir; //add local directory to "ALL" but only if it differs from root dir (true for linux) - if (GameConstants::DATA_DIR != GVCMIDirs.UserPath) + if (VCMIDirs::get().dataPath() != VCMIDirs::get().localPath()) { - userDir = shared_ptr(new CFilesystemLoader(GVCMIDirs.UserPath, 0, true)); + userDir = shared_ptr(new CFilesystemLoader(VCMIDirs::get().localPath(), 0, true)); initialLoader->addLoader("ALL/", userDir, false); } diff --git a/lib/GameConstants.h b/lib/GameConstants.h index a98b19fcb..14ef804d1 100644 --- a/lib/GameConstants.h +++ b/lib/GameConstants.h @@ -16,46 +16,6 @@ namespace GameConstants { const std::string VCMI_VERSION = "VCMI 0.92"; - /* - * DATA_DIR contains the game data (Data/, MP3/, ...). - * BIN_DIR is where the vcmiclient/vcmiserver binaries reside - * LIB_DIR is where the AI libraries reside (linux only) - */ - #if defined(_WIN32) - const std::string DATA_DIR = "."; - const std::string BIN_DIR = "."; - const std::string LIB_DIR = "."; - const std::string SERVER_NAME = "VCMI_server.exe"; - const std::string LIB_EXT = "dll"; - const std::string PATH_SEPARATOR = "\\"; - #elif defined(__APPLE__) - const std::string DATA_DIR = "../Data"; - const std::string BIN_DIR = "."; - const std::string LIB_DIR = "."; - const std::string SERVER_NAME = "./vcmiserver"; - const std::string LIB_EXT = "dylib"; - const std::string PATH_SEPARATOR = "/"; - #else - #ifndef M_DATA_DIR - #error M_DATA_DIR undefined. - #else - const std::string DATA_DIR = M_DATA_DIR; - #endif - #ifndef M_BIN_DIR - #error M_BIN_DIR undefined. - #else - const std::string BIN_DIR = M_BIN_DIR; - #endif - #ifndef M_LIB_DIR - #error M_LIB_DIR undefined. - #else - const std::string LIB_DIR = M_LIB_DIR; - #endif - const std::string SERVER_NAME = "vcmiserver"; - const std::string LIB_EXT = "so"; - const std::string PATH_SEPARATOR = "/"; - #endif - const int BFIELD_WIDTH = 17; const int BFIELD_HEIGHT = 11; const int BFIELD_SIZE = BFIELD_WIDTH * BFIELD_HEIGHT; @@ -73,13 +33,13 @@ namespace GameConstants const ui16 BACKPACK_START = 19; const int CREATURES_PER_TOWN = 7; //without upgrades const int SPELL_LEVELS = 5; + const int CRE_LEVELS = 10; // number of creature experience levels const int SPELLBOOK_GOLD_COST = 500; const int BATTLE_PENALTY_DISTANCE = 10; //if the distance is > than this, then shooting stack has distance penalty const int ARMY_SIZE = 7; const int SKILL_PER_HERO=8; - const int CRE_LEVELS = 10; const int SKILL_QUANTITY=28; const int PRIMARY_SKILLS=4; const int TERRAIN_TYPES=10; diff --git a/lib/NetPacksLib.cpp b/lib/NetPacksLib.cpp index c1894b1f9..ebe1b3c1f 100644 --- a/lib/NetPacksLib.cpp +++ b/lib/NetPacksLib.cpp @@ -829,9 +829,9 @@ DLL_LINKAGE void AssembledArtifact::applyGs( CGameState *gs ) CCombinedArtifactInstance *combinedArt = new CCombinedArtifactInstance(builtArt); gs->map->addNewArtifactInstance(combinedArt); //retrieve all constituents - BOOST_FOREACH(si32 constituentID, *builtArt->constituents) + BOOST_FOREACH(const CArtifact * constituent, *builtArt->constituents) { - ArtifactPosition pos = artSet->getArtPos(constituentID); + ArtifactPosition pos = artSet->getArtPos(constituent->id); assert(pos >= 0); CArtifactInstance *constituentInstance = artSet->getArt(pos); diff --git a/lib/VCMIDirs.cpp b/lib/VCMIDirs.cpp new file mode 100644 index 000000000..8f23cd146 --- /dev/null +++ b/lib/VCMIDirs.cpp @@ -0,0 +1,122 @@ +#include "StdInc.h" +#include "VCMIDirs.h" + +/* + * VCMIDirs.cpp, part of VCMI engine + * + * Authors: listed in file AUTHORS in main folder + * + * License: GNU General Public License v2.0 or later + * Full text of license available in license.txt file, in main folder + * + */ + +static VCMIDirs VCMIDirsGlobal; + +VCMIDirs::VCMIDirs() +{ + // initialize local directory and create folders to which VCMI needs write access + boost::filesystem::create_directory(localPath()); + boost::filesystem::create_directory(localPath() + "/config"); + boost::filesystem::create_directory(localPath() + "/Games"); +} + +VCMIDirs & VCMIDirs::get() +{ + return VCMIDirsGlobal; +} + +//FIXME: find way to at least decrease size of this ifdef (along with cleanup in CMake) +#if defined(_WIN32) + +std::string VCMIDirs::localPath() const +{ + return dataPath(); +} + +std::string VCMIDirs::libraryPath() const +{ + return dataPath(); +} + +std::string VCMIDirs::serverPath() const +{ + return dataPath() + "\\" + "VCMI_server.exe"; +} + +std::string VCMIDirs::dataPath() const +{ + return "."; +} + +std::string VCMIDirs::libraryName(std::string basename) const +{ + return basename + ".dll"; +} + +#elif defined(__APPLE__) + +std::string VCMIDirs::localPath() const +{ + // This is Cocoa code that should be normally used to get path to Application Support folder but can't use it here for now... + // NSArray* urls = [[NSFileManager defaultManager] URLsForDirectory:NSApplicationSupportDirectory inDomains:NSUserDomainMask]; + // UserPath = path([urls[0] path] + "/vcmi").string(); + + // ...so here goes a bit of hardcode instead + std::string home_dir = "."; + if (getenv("HOME") != NULL ) + home_dir = getenv("HOME"); + + return path(home_dir + "/Library/Application Support/vcmi").string(); +} + +std::string VCMIDirs::libraryPath() const +{ + return "."; +} + +std::string VCMIDirs::serverPath() const +{ + return "./vcmiserver"; +} + +std::string VCMIDirs::dataPath() const +{ + return "../Data"; +} + +std::string VCMIDirs::libraryName(std::string basename) const +{ + return "lib" + basename + ".dylib"; +} + +#else + +std::string VCMIDirs::localPath() const +{ + if (getenv("HOME") != NULL ) + return std::string(getenv("HOME")) + "/.vcmi"; + return "."; +} + +std::string VCMIDirs::libraryPath() const +{ + return M_LIB_DIR; +} + +std::string VCMIDirs::serverPath() const +{ + return std::string(M_BIN_DIR) + "/" + "vcmiserver"; +} + +std::string VCMIDirs::dataPath() const +{ + return M_DATA_DIR; +} + +std::string VCMIDirs::libraryName(std::string basename) const +{ + return "lib" + basename + ".so"; +} + +#endif diff --git a/lib/VCMIDirs.h b/lib/VCMIDirs.h index 877d25d90..2afdd23f2 100644 --- a/lib/VCMIDirs.h +++ b/lib/VCMIDirs.h @@ -12,55 +12,27 @@ * */ -#ifndef _WIN32 //we need boost here only on non-win platforms - #include - using namespace boost::filesystem; -#endif - /// Where to find the various VCMI files. This is mostly useful for linux. -class VCMIDirs { +class DLL_LINKAGE VCMIDirs +{ public: - std::string UserPath; + VCMIDirs(); - VCMIDirs() - { -#ifdef _WIN32 - UserPath = GameConstants::DATA_DIR; -#else - try { -#ifdef ANDROID - UserPath = DATA_DIR; -#elif defined(__APPLE__) - // This is Cocoa code that should be normally used to get path to Application Support folder but can't use it here for now... - // NSArray* urls = [[NSFileManager defaultManager] URLsForDirectory:NSApplicationSupportDirectory inDomains:NSUserDomainMask]; - // UserPath = path([urls[0] path] + "/vcmi").string(); - - // ...so here goes a bit of hardcode instead - std::string home_dir = "."; - if (getenv("HOME") != NULL ) - home_dir = getenv("HOME"); - - UserPath = path(home_dir + "/Library/Application Support/vcmi").string(); -#else - // Find vcmi user directory and create it if necessary - std::string home_dir = "."; - if (getenv("HOME") != NULL ) - home_dir = getenv("HOME"); + /// get singleton instance + static VCMIDirs & get(); - UserPath = path(home_dir + "/.vcmi").string(); -#endif - create_directory(UserPath); - create_directory(UserPath + "/config"); - create_directory(UserPath + "/Games"); + /// Path to local, user-specific directory (e.g. ~/.vcmi on *nix systems) + std::string localPath() const; - /* Home directory can contain some extra maps. */ - create_directory(UserPath + "/Maps"); - } - catch(const std::exception & e) - { - } -#endif - } + /// Path where vcmi libraries can be found (in AI and Scripting subdirectories) + std::string libraryPath() const; + + /// Path to vcmiserver, including server name (e.g. /usr/bin/vcmiserver) + std::string serverPath() const; + + /// Path to global system-wide data directory + std::string dataPath() const; + + /// Returns system-specific name for dynamic libraries ("libStupidAI.so" or "StupidAI.dll") + std::string libraryName(std::string basename) const; }; - -extern DLL_LINKAGE VCMIDirs GVCMIDirs; diff --git a/lib/VCMI_Lib.cpp b/lib/VCMI_Lib.cpp index 1759b0ea9..aa1fe43af 100644 --- a/lib/VCMI_Lib.cpp +++ b/lib/VCMI_Lib.cpp @@ -29,8 +29,6 @@ LibClasses * VLC = NULL; -DLL_LINKAGE VCMIDirs GVCMIDirs; - DLL_LINKAGE void preinitDLL(CConsoleHandler *Console, std::ostream *Logfile) { console = Console; diff --git a/server/CVCMIServer.cpp b/server/CVCMIServer.cpp index 4355d624b..1909c7a0d 100644 --- a/server/CVCMIServer.cpp +++ b/server/CVCMIServer.cpp @@ -505,7 +505,7 @@ int _tmain(int argc, _TCHAR* argv[]) int main(int argc, char** argv) #endif { - logfile = new std::ofstream((GVCMIDirs.UserPath + "/VCMI_Server_log.txt").c_str()); + logfile = new std::ofstream((VCMIDirs::get().localPath() + "/VCMI_Server_log.txt").c_str()); console = new CConsoleHandler; //boost::thread t(boost::bind(&CConsoleHandler::run,::console)); if(argc > 1)