diff --git a/AI/BattleAI/main.cpp b/AI/BattleAI/main.cpp index 5432c3037..fa9b67a7d 100644 --- a/AI/BattleAI/main.cpp +++ b/AI/BattleAI/main.cpp @@ -7,7 +7,7 @@ #define strcpy_s(a, b, c) strncpy(a, c, b) #endif -#ifdef __ANDROID__ +#ifdef VCMI_ANDROID #define GetGlobalAiVersion BattleAI_GetGlobalAiVersion #define GetAiName BattleAI_GetAiName #define GetNewBattleAI BattleAI_GetNewBattleAI diff --git a/AI/StupidAI/main.cpp b/AI/StupidAI/main.cpp index 07cfedee2..70ab20a03 100644 --- a/AI/StupidAI/main.cpp +++ b/AI/StupidAI/main.cpp @@ -7,7 +7,7 @@ #define strcpy_s(a, b, c) strncpy(a, c, b) #endif -#ifdef __ANDROID__ +#ifdef VCMI_ANDROID #define GetGlobalAiVersion StupidAI_GetGlobalAiVersion #define GetAiName StupidAI_GetAiName #define GetNewBattleAI StupidAI_GetNewBattleAI diff --git a/AI/VCAI/main.cpp b/AI/VCAI/main.cpp index 26f3e52c6..04f15137c 100644 --- a/AI/VCAI/main.cpp +++ b/AI/VCAI/main.cpp @@ -5,7 +5,7 @@ #define strcpy_s(a, b, c) strncpy(a, c, b) #endif -#ifdef __ANDROID__ +#ifdef VCMI_ANDROID #define GetGlobalAiVersion VCAI_GetGlobalAiVersion #define GetAiName VCAI_GetAiName #define GetNewAI VCAI_GetNewAI diff --git a/ChangeLog b/ChangeLog index 18fba62ce..77f519c0f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,6 +3,8 @@ GENERAL: * VCMI can now be compiled with SDL2 * Better upscaling when running in fullscreen mode. * Non-latin characters can now be entered in chat window or used for save names. +* (windows) Moved VCMI data directory from '%userprofile%\vcmi' to '%userprofile%\Documents\My Games\vcmi' +* (windows, OSX) Moved VCMI save directory from 'VCMI_DATA\Games' to 'VCMI_DATA\Saves' RANDOM MAP GENERATOR: diff --git a/Global.h b/Global.h index baa9ee036..b63219e8e 100644 --- a/Global.h +++ b/Global.h @@ -49,10 +49,58 @@ static_assert(sizeof(bool) == 1, "Bool needs to be 1 byte in size."); # pragma warning (disable : 4800 ) /* disable conversion to bool warning -- I think it's intended in all places */ #endif +/* ---------------------------------------------------------------------------- */ +/* System detection. */ +/* ---------------------------------------------------------------------------- */ +// Based on: http://sourceforge.net/p/predef/wiki/OperatingSystems/ +// and on: http://stackoverflow.com/questions/5919996/how-to-detect-reliably-mac-os-x-ios-linux-windows-in-c-preprocessor +// TODO?: Should be moved to vstd\os_detect.h (and then included by Global.h) +#ifdef _WIN16 // Defined for 16-bit environments +# error "16-bit Windows isn't supported" +#elif defined(_WIN64) // Defined for 64-bit environments +# define VCMI_WINDOWS +# define VCMI_WINDOWS_64 +#elif defined(_WIN32) // Defined for both 32-bit and 64-bit environments +# define VCMI_WINDOWS +# define VCMI_WINDOWS_32 +#elif defined(_WIN32_WCE) +# error "Windows CE isn't supported" +#elif defined(__linux__) || defined(__gnu_linux__) || defined(linux) || defined(__linux) +# define VCMI_UNIX +# define VCMI_LINUX +# ifdef __ANDROID__ +# define VCMI_ANDROID +# endif +#elif defined(__APPLE__) && defined(__MACH__) +# define VCMI_UNIX +# define VCMI_APPLE +# include "TargetConditionals.h" +# if TARGET_IPHONE_SIMULATOR +# define VCMI_IOS +# define VCMI_IOS_SIM +# elif TARGET_OS_IPHONE +# define VCMI_IOS +# elif TARGET_OS_MAC +# define VCMI_MAC +# else +//# warning "Unknown Apple target."? +# endif +#else +# error "VCMI supports only Windows, OSX, Linux and Android targets" +#endif + +#ifdef VCMI_IOS +# error "iOS system isn't yet supported." +#endif + /* ---------------------------------------------------------------------------- */ /* Commonly used C++, Boost headers */ /* ---------------------------------------------------------------------------- */ -#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +#ifdef VCMI_WINDOWS +# define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers - delete this line if something is missing. +# define NOMINMAX // Exclude min/max macros from . Use std::[min/max] from instead. +#endif + #define _USE_MATH_DEFINES #include @@ -86,7 +134,7 @@ static_assert(sizeof(bool) == 1, "Bool needs to be 1 byte in size."); #define BOOST_FILESYSTEM_VERSION 3 #if BOOST_VERSION > 105000 -#define BOOST_THREAD_VERSION 3 +# define BOOST_THREAD_VERSION 3 #endif #define BOOST_THREAD_DONT_PROVIDE_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE 1 #define BOOST_BIND_NO_PLACEHOLDERS @@ -99,9 +147,12 @@ static_assert(sizeof(bool) == 1, "Bool needs to be 1 byte in size."); #include #include #include +#include +#include #include #include #include +#include #include #include #include @@ -112,13 +163,8 @@ static_assert(sizeof(bool) == 1, "Bool needs to be 1 byte in size."); #include #include - -#ifdef ANDROID -#include -#endif - #ifndef M_PI -#define M_PI 3.14159265358979323846 +# define M_PI 3.14159265358979323846 #endif /* ---------------------------------------------------------------------------- */ @@ -151,30 +197,20 @@ typedef boost::lock_guard TLockGuardRec; /* Macros */ /* ---------------------------------------------------------------------------- */ // Import + Export macro declarations -#ifdef _WIN32 +#ifdef VCMI_WINDOWS # ifdef __GNUC__ +# define DLL_IMPORT __attribute__((dllimport)) # define DLL_EXPORT __attribute__((dllexport)) # else +# define DLL_IMPORT __declspec(dllimport) # define DLL_EXPORT __declspec(dllexport) # endif # define ELF_VISIBILITY #else # ifdef __GNUC__ +# define DLL_IMPORT __attribute__ ((visibility("default"))) # define DLL_EXPORT __attribute__ ((visibility("default"))) # define ELF_VISIBILITY __attribute__ ((visibility("default"))) -# endif -#endif - -#ifdef _WIN32 -# ifdef __GNUC__ -# define DLL_IMPORT __attribute__((dllimport)) -# else -# define DLL_IMPORT __declspec(dllimport) -# endif -# define ELF_VISIBILITY -#else -# ifdef __GNUC__ -# define DLL_IMPORT __attribute__ ((visibility("default"))) # define ELF_VISIBILITY __attribute__ ((visibility("default"))) # endif #endif diff --git a/client/CMT.cpp b/client/CMT.cpp index 4b3b8bdbe..7648aad9d 100644 --- a/client/CMT.cpp +++ b/client/CMT.cpp @@ -41,7 +41,7 @@ #include "../lib/logging/CBasicLogConfigurator.h" #include "../lib/CondSh.h" -#ifdef _WIN32 +#ifdef VCMI_WINDOWS #include "SDL_syswm.h" #endif #include "../lib/UnlockGuard.h" @@ -52,6 +52,7 @@ #endif namespace po = boost::program_options; +namespace bfs = boost::filesystem; /* * CMT.cpp, part of VCMI engine @@ -73,13 +74,12 @@ int preferredDriverIndex = -1; SDL_Window * mainWindow = nullptr; SDL_Renderer * mainRenderer = nullptr; SDL_Texture * screenTexture = nullptr; - #endif // VCMI_SDL1 extern boost::thread_specific_ptr inGuiThread; SDL_Surface *screen = nullptr, //main screen surface - *screen2 = nullptr,//and hlp surface (used to store not-active interfaces layer) + *screen2 = nullptr, //and hlp surface (used to store not-active interfaces layer) *screenBuf = screen; //points to screen (if only advmapint is present) or screen2 (else) - should be used when updating controls which are not regularly redrawed std::queue events; @@ -100,31 +100,29 @@ static void mainLoop(); void startGame(StartInfo * options, CConnection *serv = nullptr); void endGame(); -#ifndef _WIN32 +#ifndef VCMI_WINDOWS #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #include #endif -void startGameFromFile(const std::string &fname) +void startGameFromFile(const bfs::path &fname) { StartInfo si; try //attempt retrieving start info from given file { - if(!fname.size() || !boost::filesystem::exists(fname)) - throw std::runtime_error("Startfile \"" + fname + "\" does not exist!"); + if(fname.empty() || !bfs::exists(fname)) + throw std::runtime_error("Startfile \"" + fname.string() + "\" does not exist!"); CLoadFile out(fname); - if(!out.sfile || !*out.sfile) - { - throw std::runtime_error("Cannot read from startfile \"" + fname + "\"!"); - } + if (!out.sfile || !*out.sfile) + throw std::runtime_error("Cannot read from startfile \"" + fname.string() +"\"!"); out >> si; } catch(std::exception &e) { - logGlobal->errorStream() << "Failed to start from the file: " + fname << ". Error: " << e.what() + logGlobal->errorStream() << "Failed to start from the file: " << fname << ". Error: " << e.what() << " Falling back to main menu."; GH.curInt = CGPreGame::create(); return; @@ -184,19 +182,19 @@ static void prog_help(const po::options_description &opts) // printf(" -v, --version display version information and exit\n"); } -#ifdef __APPLE__ +#ifdef VCMI_APPLE void OSX_checkForUpdates(); #endif -#if defined(_WIN32) && !defined (__GNUC__) +#if defined(VCMI_WINDOWS) && !defined (__GNUC__) int wmain(int argc, wchar_t* argv[]) -#elif defined(__APPLE__) +#elif defined(VCMI_APPLE) int SDL_main(int argc, char *argv[]) #else int main(int argc, char** argv) #endif { -#ifdef __APPLE__ +#ifdef VCMI_APPLE // Correct working dir executable folder (not bundle folder) so we can use executable relative paths std::string executablePath = argv[0]; std::string workDir = executablePath.substr(0, executablePath.rfind('/')); @@ -206,7 +204,7 @@ int main(int argc, char** argv) OSX_checkForUpdates(); // Check that game data is prepared. Otherwise run vcmibuilder helper application - FILE* check = fopen((VCMIDirs::get().userDataPath() + "/game_data_prepared").c_str(), "r"); + FILE* check = fopen((VCMIDirs::get().userDataPath() / "game_data_prepared").string().c_str(), "r"); if (check == nullptr) { system("open ./vcmibuilder.app"); return 0; @@ -219,7 +217,7 @@ int main(int argc, char** argv) ("help,h", "display help and exit") ("version,v", "display version information and exit") ("battle,b", po::value(), "runs game in duel mode (battle-only") - ("start", po::value(), "starts game from saved StartInfo file") + ("start", po::value(), "starts game from saved StartInfo file") ("onlyAI", "runs without human player, all players will be default AI") ("noGUI", "runs without GUI, implies --onlyAI") ("ai", po::value>(), "AI to be used for the player, can be specified several times for the consecutive players") @@ -272,17 +270,17 @@ int main(int argc, char** argv) CStopWatch total, pomtime; std::cout.flags(std::ios::unitbuf); console = new CConsoleHandler; - *console->cb = std::bind(&processCommand, _1); + *console->cb = processCommand; console->start(); atexit(dispose); - const auto logPath = VCMIDirs::get().userCachePath() + "/VCMI_Client_log.txt"; + const bfs::path logPath = VCMIDirs::get().userCachePath() / "VCMI_Client_log.txt"; CBasicLogConfigurator logConfig(logPath, console); logConfig.configureDefault(); logGlobal->infoStream() << "Creating console and configuring logger: " << pomtime.getDiff(); logGlobal->infoStream() << "The log file will be saved to " << logPath; -#ifdef __ANDROID__ +#ifdef VCMI_ANDROID // boost will crash without this setenv("LANG", "C", 1); #endif @@ -388,7 +386,7 @@ int main(int argc, char** argv) logGlobal->infoStream()<<"\tInitializing video: "<(); + fileToStartFrom = vm["start"].as(); - if(fileToStartFrom.size() && boost::filesystem::exists(fileToStartFrom)) + if(!fileToStartFrom.empty() && bfs::exists(fileToStartFrom)) startGameFromFile(fileToStartFrom); //ommit pregame and start the game using settings from file else { - if(fileToStartFrom.size()) + if(!fileToStartFrom.empty()) { logGlobal->warnStream() << "Warning: cannot find given file to start from (" << fileToStartFrom << "). Falling back to main menu."; @@ -584,7 +582,8 @@ void processCommand(const std::string &message) { std::cout<<"Command accepted.\t"; - std::string outPath = VCMIDirs::get().userCachePath() + "/extracted/"; + const bfs::path outPath = + VCMIDirs::get().userCachePath() / "extracted"; auto list = CResourceHandler::get()->getFilteredFiles([](const ResourceID & ident) { @@ -593,18 +592,18 @@ void processCommand(const std::string &message) for (auto & filename : list) { - std::string outName = outPath + filename.getName(); + const bfs::path filePath = outPath / (filename.getName() + ".TXT"); + + bfs::create_directories(filePath.parent_path()); - boost::filesystem::create_directories(outName.substr(0, outName.find_last_of("/"))); - - std::ofstream file(outName + ".TXT"); + bfs::ofstream file(filePath); auto text = CResourceHandler::get()->load(filename)->readAll(); file.write((char*)text.first.get(), text.second); } std::cout << "\rExtracting done :)\n"; - std::cout << " Extracted files can be found in " << outPath << " directory\n"; + std::cout << " Extracted files can be found in " << outPath << " directory\n"; } else if(cn=="crash") { @@ -710,15 +709,13 @@ void processCommand(const std::string &message) { CDefEssential * cde = CDefHandler::giveDefEss(URI); - std::string outName = URI; - std::string outPath = VCMIDirs::get().userCachePath() + "/extracted/"; + const bfs::path outPath = VCMIDirs::get().userCachePath() / "extracted" / URI; + bfs::create_directories(outPath); - boost::filesystem::create_directories(outPath + outName); - - for (size_t i=0; iourImages.size(); i++) + for (size_t i = 0; i < cde->ourImages.size(); ++i) { - std::string filename = outPath + outName + '/' + boost::lexical_cast(i) + ".bmp"; - SDL_SaveBMP(cde->ourImages[i].bitmap, filename.c_str()); + const bfs::path filePath = outPath / (boost::lexical_cast(i)+".bmp"); + SDL_SaveBMP(cde->ourImages[i].bitmap, filePath.string().c_str()); } } else @@ -731,14 +728,12 @@ void processCommand(const std::string &message) if (CResourceHandler::get()->existsResource(ResourceID(URI))) { - std::string outName = URI; - std::string outPath = VCMIDirs::get().userCachePath() + "/extracted/"; - std::string fullPath = outPath + outName; + const bfs::path outPath = VCMIDirs::get().userCachePath() / "extracted" / URI; auto data = CResourceHandler::get()->load(ResourceID(URI))->readAll(); - boost::filesystem::create_directories(fullPath.substr(0, fullPath.find_last_of("/"))); - std::ofstream outFile(outPath + outName, std::ofstream::binary); + bfs::create_directories(outPath.parent_path()); + bfs::ofstream outFile(outPath, bfs::ofstream::binary); outFile.write((char*)data.first.get(), data.second); } else @@ -1013,7 +1008,7 @@ static void setScreenRes(int w, int h, int bpp, bool fullscreen, bool resetVideo SDL_ShowCursor(SDL_DISABLE); SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL); -#ifdef _WIN32 +#ifdef VCMI_WINDOWS SDL_SysWMinfo wm; SDL_VERSION(&wm.version); int getwm = SDL_GetWMInfo(&wm); diff --git a/client/CPlayerInterface.cpp b/client/CPlayerInterface.cpp index c1c8203bb..75267ebce 100644 --- a/client/CPlayerInterface.cpp +++ b/client/CPlayerInterface.cpp @@ -42,13 +42,6 @@ #include "../lib/UnlockGuard.h" #include -#ifdef min -#undef min -#endif -#ifdef max -#undef max -#endif - /* * CPlayerInterface.cpp, part of VCMI engine * @@ -1622,22 +1615,20 @@ int CPlayerInterface::getLastIndex( std::string namePrefix) path gamesDir = VCMIDirs::get().userSavePath(); std::map dates; //save number => datestamp - directory_iterator enddir; + const directory_iterator enddir; if(!exists(gamesDir)) create_directory(gamesDir); - - for (directory_iterator dir(gamesDir); dir!=enddir; dir++) + else + for (directory_iterator dir(gamesDir); dir != enddir; ++dir) { if(is_regular(dir->status())) { - std::string name = dir->path().leaf().string(); + std::string name = dir->path().filename().string(); if(starts_with(name, namePrefix) && ends_with(name, ".vcgm1")) { char nr = name[namePrefix.size()]; if(std::isdigit(nr)) - { dates[last_write_time(dir->path())] = boost::lexical_cast(nr); - } } } } diff --git a/client/CVideoHandler.cpp b/client/CVideoHandler.cpp index 84f0c18cb..894d7871f 100644 --- a/client/CVideoHandler.cpp +++ b/client/CVideoHandler.cpp @@ -23,7 +23,7 @@ static bool keyDown() } #endif -#if defined(_WIN32) && (_MSC_VER < 1800 || !defined(USE_FFMPEG)) +#if defined(VCMI_WINDOWS) && (_MSC_VER < 1800 || !defined(USE_FFMPEG)) void checkForError(bool throwing = true) { diff --git a/client/CVideoHandler.h b/client/CVideoHandler.h index a300d93b9..1acd312a0 100644 --- a/client/CVideoHandler.h +++ b/client/CVideoHandler.h @@ -43,9 +43,8 @@ public: }; -#if defined(_WIN32) && (_MSC_VER < 1800 || !defined(USE_FFMPEG)) +#if defined(VCMI_WINDOWS) && (_MSC_VER < 1800 || !defined(USE_FFMPEG)) -#define WIN32_LEAN_AND_MEAN //excludes rarely used stuff from windows headers - delete this line if something is missing #include #pragma pack(push,1) diff --git a/client/Client.cpp b/client/Client.cpp index da111da6c..b02abab20 100644 --- a/client/Client.cpp +++ b/client/Client.cpp @@ -20,7 +20,7 @@ #include "../lib/CBuildingHandler.h" #include "../lib/CSpellHandler.h" #include "../lib/Connection.h" -#ifndef __ANDROID__ +#ifndef VCMI_ANDROID #include "../lib/Interprocess.h" #endif #include "../lib/NetPacks.h" @@ -40,7 +40,7 @@ #include "CMT.h" extern std::string NAME; -#ifndef __ANDROID__ +#ifndef VCMI_ANDROID namespace intpr = boost::interprocess; #endif @@ -780,8 +780,9 @@ std::string CClient::aiNameForPlayer(const PlayerSettings &ps, bool battleAI) { if(ps.name.size()) { - std::string filename = VCMIDirs::get().libraryPath() + "/AI/" + VCMIDirs::get().libraryName(ps.name); - if(boost::filesystem::exists(filename)) + const boost::filesystem::path aiPath = + VCMIDirs::get().libraryPath() / "AI" / VCMIDirs::get().libraryName(ps.name); + if (boost::filesystem::exists(aiPath)) return ps.name; } @@ -814,7 +815,7 @@ void CServerHandler::waitForServer() startServer(); th.update(); -#ifndef __ANDROID__ +#ifndef VCMI_ANDROID intpr::scoped_lock slock(shared->sr->mutex); while(!shared->sr->ready) { @@ -827,7 +828,7 @@ void CServerHandler::waitForServer() CConnection * CServerHandler::connectToServer() { -#ifndef __ANDROID__ +#ifndef VCMI_ANDROID if(!shared->sr->ready) waitForServer(); #else @@ -850,7 +851,7 @@ CServerHandler::CServerHandler(bool runServer /*= false*/) port = boost::lexical_cast(settings["server"]["port"].Float()); verbose = true; -#ifndef __ANDROID__ +#ifndef VCMI_ANDROID boost::interprocess::shared_memory_object::remove("vcmi_memory"); //if the application has previously crashed, the memory may not have been removed. to avoid problems - try to destroy it try { @@ -868,8 +869,8 @@ CServerHandler::~CServerHandler() void CServerHandler::callServer() { setThreadName("CServerHandler::callServer"); - std::string logName = VCMIDirs::get().userCachePath() + "/server_log.txt"; - std::string comm = VCMIDirs::get().serverPath() + " --port=" + port + " > " + logName; + const std::string logName = (VCMIDirs::get().userCachePath() / "server_log.txt").string(); + const std::string comm = VCMIDirs::get().serverPath().string() + " --port=" + port + " > \"" + logName + '\"'; int result = std::system(comm.c_str()); if (result == 0) logNetwork->infoStream() << "Server closed correctly"; diff --git a/editor/Editor.cpp b/editor/Editor.cpp index 822ac1d89..158662630 100644 --- a/editor/Editor.cpp +++ b/editor/Editor.cpp @@ -13,7 +13,7 @@ Editor::Editor(QWidget *parent) { // Setup default logging(enough for now) console = new CConsoleHandler; - CBasicLogConfigurator logConfig(VCMIDirs::get().userCachePath() + "/VCMI_Editor_log.txt", console); + CBasicLogConfigurator logConfig(VCMIDirs::get().userCachePath() / "VCMI_Editor_log.txt", console); logConfig.configureDefault(); preinitDLL(console); diff --git a/launcher/StdInc.h b/launcher/StdInc.h index 751c21f85..aa3a6b8fe 100644 --- a/launcher/StdInc.h +++ b/launcher/StdInc.h @@ -8,4 +8,13 @@ #include #include #include -#include \ No newline at end of file +#include + +inline QString pathToQString(const boost::filesystem::path & path) +{ +#ifdef VCMI_WINDOWS + return QString::fromStdWString(path.wstring()); +#else + return QString::fromStdString(path.string()); +#endif +} \ No newline at end of file diff --git a/launcher/launcherdirs.cpp b/launcher/launcherdirs.cpp index 6e28e273a..d7b3b453d 100644 --- a/launcher/launcherdirs.cpp +++ b/launcher/launcherdirs.cpp @@ -18,10 +18,10 @@ CLauncherDirs & CLauncherDirs::get() QString CLauncherDirs::downloadsPath() { - return QString::fromUtf8(VCMIDirs::get().userCachePath().c_str()) + "/downloads"; + return pathToQString(VCMIDirs::get().userCachePath() / "downloads"); } QString CLauncherDirs::modsPath() { - return QString::fromUtf8(VCMIDirs::get().userDataPath().c_str()) + "/Mods"; + return pathToQString(VCMIDirs::get().userDataPath() / "Mods"); } diff --git a/launcher/mainwindow_moc.cpp b/launcher/mainwindow_moc.cpp index f7cee2d17..3536e925a 100644 --- a/launcher/mainwindow_moc.cpp +++ b/launcher/mainwindow_moc.cpp @@ -13,15 +13,15 @@ void MainWindow::load() { console = new CConsoleHandler; - CBasicLogConfigurator logConfig(VCMIDirs::get().userCachePath() + "/VCMI_Launcher_log.txt", console); + CBasicLogConfigurator logConfig(VCMIDirs::get().userCachePath() / "VCMI_Launcher_log.txt", console); logConfig.configureDefault(); CResourceHandler::initialize(); CResourceHandler::load("config/filesystem.json"); for (auto & string : VCMIDirs::get().dataPaths()) - QDir::addSearchPath("icons", QString::fromUtf8(string.c_str()) + "/launcher/icons"); - QDir::addSearchPath("icons", QString::fromUtf8(VCMIDirs::get().userDataPath().c_str()) + "/launcher/icons"); + QDir::addSearchPath("icons", pathToQString(string / "launcher" / "icons")); + QDir::addSearchPath("icons", pathToQString(VCMIDirs::get().userDataPath() / "launcher" / "icons")); settings.init(); } @@ -46,7 +46,7 @@ MainWindow::~MainWindow() void MainWindow::on_startGameButon_clicked() { - startExecutable(QString::fromUtf8(VCMIDirs::get().clientPath().c_str())); + startExecutable(pathToQString(VCMIDirs::get().clientPath())); } void MainWindow::startExecutable(QString name) diff --git a/launcher/modManager/cmodmanager.cpp b/launcher/modManager/cmodmanager.cpp index 8fff2af44..40f00dcb4 100644 --- a/launcher/modManager/cmodmanager.cpp +++ b/launcher/modManager/cmodmanager.cpp @@ -39,7 +39,7 @@ CModManager::CModManager(CModList * modList): QString CModManager::settingsPath() { - return QString::fromUtf8(VCMIDirs::get().userConfigPath().c_str()) + "/modSettings.json"; + return pathToQString(VCMIDirs::get().userConfigPath() / "modSettings.json"); } void CModManager::loadModSettings() diff --git a/launcher/settingsView/csettingsview_moc.cpp b/launcher/settingsView/csettingsview_moc.cpp index 9013d836e..9f19a70bf 100644 --- a/launcher/settingsView/csettingsview_moc.cpp +++ b/launcher/settingsView/csettingsview_moc.cpp @@ -46,9 +46,9 @@ void CSettingsView::loadSettings() for (auto entry : urls.Vector()) ui->plainTextEditRepos->appendPlainText(QString::fromUtf8(entry.String().c_str())); - ui->lineEditUserDataDir->setText(QString::fromUtf8(VCMIDirs::get().userDataPath().c_str())); - ui->lineEditGameDir->setText(QString::fromUtf8(M_DATA_DIR)); - ui->lineEditTempDir->setText(QString::fromUtf8(VCMIDirs::get().userCachePath().c_str())); + ui->lineEditUserDataDir->setText(pathToQString(VCMIDirs::get().userDataPath())); + ui->lineEditGameDir->setText(pathToQString(VCMIDirs::get().binaryPath())); + ui->lineEditTempDir->setText(pathToQString(VCMIDirs::get().userCachePath())); std::string encoding = settings["general"]["encoding"].String(); size_t encodingIndex = boost::range::find(knownEncodingsList, encoding) - knownEncodingsList; diff --git a/lib/BattleHex.cpp b/lib/BattleHex.cpp index 654197d44..659de94cb 100644 --- a/lib/BattleHex.cpp +++ b/lib/BattleHex.cpp @@ -44,18 +44,6 @@ BattleHex& BattleHex::moveInDir(EDir dir, bool hasToBeValid) return *this; } -void BattleHex::operator+=(EDir dir) -{ - moveInDir(dir); -} - -BattleHex BattleHex::operator+(EDir dir) const -{ - BattleHex ret(*this); - ret += dir; - return ret; -} - std::vector BattleHex::neighbouringTiles() const { std::vector ret; @@ -93,17 +81,18 @@ char BattleHex::getDistance(BattleHex hex1, BattleHex hex2) { int y1 = hex1.getY(), y2 = hex2.getY(); - - int x1 = hex1.getX() + y1 / 2.0, - x2 = hex2.getX() + y2 / 2.0; + + // FIXME: Omit floating point arithmetics + int x1 = (int)(hex1.getX() + y1 * 0.5), + x2 = (int)(hex2.getX() + y2 * 0.5); int xDst = x2 - x1, yDst = y2 - y1; if ((xDst >= 0 && yDst >= 0) || (xDst < 0 && yDst < 0)) return std::max(std::abs(xDst), std::abs(yDst)); - else - return std::abs(xDst) + std::abs(yDst); + + return std::abs(xDst) + std::abs(yDst); } void BattleHex::checkAndPush(BattleHex tile, std::vector & ret) diff --git a/lib/BattleHex.h b/lib/BattleHex.h index 48c53c007..26042e7b4 100644 --- a/lib/BattleHex.h +++ b/lib/BattleHex.h @@ -17,22 +17,16 @@ struct DLL_LINKAGE BattleHex { static const si16 INVALID = -1; - enum EDir{RIGHT, BOTTOM_RIGHT, BOTTOM_LEFT, LEFT, TOP_LEFT, TOP_RIGHT}; + enum EDir { RIGHT, BOTTOM_RIGHT, BOTTOM_LEFT, LEFT, TOP_LEFT, TOP_RIGHT }; si16 hex; BattleHex() : hex(INVALID) {} BattleHex(si16 _hex) : hex(_hex) {} - operator si16() const - { - return hex; - } + operator si16() const { return hex; } - bool isValid() const - { - return hex >= 0 && hex < GameConstants::BFIELD_SIZE; - } + bool isValid() const { return hex >= 0 && hex < GameConstants::BFIELD_SIZE; } template BattleHex(inttype x, inttype y) @@ -61,9 +55,7 @@ struct DLL_LINKAGE BattleHex void setXY(si16 x, si16 y, bool hasToBeValid = true) { if(hasToBeValid) - { - assert(x >= 0 && x < GameConstants::BFIELD_WIDTH && y >= 0 && y < GameConstants::BFIELD_HEIGHT); - } + assert(x >= 0 && x < GameConstants::BFIELD_WIDTH && y >= 0 && y < GameConstants::BFIELD_HEIGHT); hex = x + y * GameConstants::BFIELD_WIDTH; } @@ -73,28 +65,23 @@ struct DLL_LINKAGE BattleHex setXY(xy.first, xy.second); } - si16 getY() const - { - return hex / GameConstants::BFIELD_WIDTH; - } + si16 getY() const { return hex / GameConstants::BFIELD_WIDTH; } + si16 getX() const { return hex % GameConstants::BFIELD_WIDTH; } - si16 getX() const - { - int pos = hex - getY() * GameConstants::BFIELD_WIDTH; - return pos; - } - - std::pair getXY() const - { - return std::make_pair(getX(), getY()); - } + std::pair getXY() const { return std::make_pair(getX(), getY()); } //moving to direction BattleHex& moveInDir(EDir dir, bool hasToBeValid = true); - void operator+=(EDir dir); //sugar for above + BattleHex& operator+=(EDir dir) { return moveInDir(dir); } //sugar for above //generates new BattleHex moved by given dir - BattleHex operator+(EDir dir) const; + BattleHex movedInDir(EDir dir, bool hasToBeValid = true) const + { + BattleHex result(*this); + result.moveInDir(dir, hasToBeValid); + return result; + } + BattleHex operator+(EDir dir) const { return movedInDir(dir); } std::vector neighbouringTiles() const; diff --git a/lib/CConsoleHandler.cpp b/lib/CConsoleHandler.cpp index 6648386ba..29407207a 100644 --- a/lib/CConsoleHandler.cpp +++ b/lib/CConsoleHandler.cpp @@ -17,7 +17,7 @@ boost::mutex CConsoleHandler::smx; DLL_LINKAGE CConsoleHandler * console = nullptr; -#ifndef _WIN32 +#ifndef VCMI_WINDOWS typedef std::string TColor; #define CONSOLE_GREEN "\x1b[1;32m" #define CONSOLE_RED "\x1b[1;31m" @@ -27,7 +27,6 @@ DLL_LINKAGE CConsoleHandler * console = nullptr; #define CONSOLE_GRAY "\x1b[1;30m" #define CONSOLE_TEAL "\x1b[1;36m" #else - #define WIN32_LEAN_AND_MEAN //excludes rarely used stuff from windows headers - delete this line if something is missing #include #ifndef __MINGW32__ #include @@ -36,6 +35,7 @@ DLL_LINKAGE CConsoleHandler * console = nullptr; typedef WORD TColor; HANDLE handleIn; HANDLE handleOut; + HANDLE handleErr; #define CONSOLE_GREEN FOREGROUND_GREEN | FOREGROUND_INTENSITY #define CONSOLE_RED FOREGROUND_RED | FOREGROUND_INTENSITY #define CONSOLE_MAGENTA FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY @@ -43,11 +43,13 @@ DLL_LINKAGE CConsoleHandler * console = nullptr; #define CONSOLE_WHITE FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY #define CONSOLE_GRAY FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE #define CONSOLE_TEAL FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY + + static TColor defErrColor; #endif static TColor defColor; -#ifdef _WIN32 +#ifdef VCMI_WINDOWS void printWinError() { @@ -178,8 +180,11 @@ void CConsoleHandler::setColor(EConsoleTextColor::EConsoleTextColor color) colorCode = defColor; break; } -#ifdef _WIN32 +#ifdef VCMI_WINDOWS SetConsoleTextAttribute(handleOut, colorCode); + if (color == EConsoleTextColor::DEFAULT) + colorCode = defErrColor; + SetConsoleTextAttribute(handleErr, colorCode); #else std::cout << colorCode; #endif @@ -194,7 +199,7 @@ int CConsoleHandler::run() while ( std::cin.good() ) { -#ifndef _WIN32 +#ifndef VCMI_WINDOWS //check if we have some unreaded symbols if (std::cin.rdbuf()->in_avail()) { @@ -216,12 +221,17 @@ int CConsoleHandler::run() } CConsoleHandler::CConsoleHandler() : thread(nullptr) { -#ifdef _WIN32 +#ifdef VCMI_WINDOWS handleIn = GetStdHandle(STD_INPUT_HANDLE); handleOut = GetStdHandle(STD_OUTPUT_HANDLE); + handleErr = GetStdHandle(STD_ERROR_HANDLE); + CONSOLE_SCREEN_BUFFER_INFO csbi; GetConsoleScreenBufferInfo(handleOut,&csbi); defColor = csbi.wAttributes; + + GetConsoleScreenBufferInfo(handleErr, &csbi); + defErrColor = csbi.wAttributes; #ifndef _DEBUG SetUnhandledExceptionFilter(onUnhandledException); #endif @@ -241,7 +251,7 @@ void CConsoleHandler::end() { if (thread) { -#ifndef _WIN32 +#ifndef VCMI_WINDOWS thread->interrupt(); #else TerminateThread(thread->native_handle(),0); diff --git a/lib/CConsoleHandler.h b/lib/CConsoleHandler.h index 83a5d892b..cbf342266 100644 --- a/lib/CConsoleHandler.h +++ b/lib/CConsoleHandler.h @@ -38,7 +38,7 @@ public: template void print(const T &data, bool addNewLine = false, EConsoleTextColor::EConsoleTextColor color = EConsoleTextColor::DEFAULT, bool printToStdErr = false) { TLockGuard _(smx); -#ifndef _WIN32 +#ifndef VCMI_WINDOWS // with love from ffmpeg - library is trying to print some warnings from separate thread // this results in broken console on Linux. Lock stdout to print all our data at once flockfile(stdout); @@ -70,7 +70,7 @@ public: } if(color != EConsoleTextColor::DEFAULT) setColor(EConsoleTextColor::DEFAULT); -#ifndef _WIN32 +#ifndef VCMI_WINDOWS funlockfile(stdout); #endif } diff --git a/lib/CGameInterface.cpp b/lib/CGameInterface.cpp index c438e0d55..5dcb444b2 100644 --- a/lib/CGameInterface.cpp +++ b/lib/CGameInterface.cpp @@ -4,8 +4,7 @@ #include "BattleState.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 +#ifdef VCMI_WINDOWS #include //for .dll libs #else #include @@ -22,7 +21,7 @@ * */ -#ifdef __ANDROID__ +#ifdef VCMI_ANDROID // we can't use shared libraries on Android so here's a hack extern "C" DLL_EXPORT void VCAI_GetAiName(char* name); extern "C" DLL_EXPORT void VCAI_GetNewAI(shared_ptr &out); @@ -35,7 +34,7 @@ extern "C" DLL_EXPORT void BattleAI_GetNewBattleAI(shared_ptr -shared_ptr createAny(std::string dllname, std::string methodName) +shared_ptr createAny(const boost::filesystem::path& libpath, const std::string& methodName) { typedef void(*TGetAIFun)(shared_ptr&); typedef void(*TGetNameFun)(char*); @@ -45,56 +44,60 @@ shared_ptr createAny(std::string dllname, std::string methodName) TGetAIFun getAI = nullptr; TGetNameFun getName = nullptr; -#ifdef __ANDROID__ +#ifdef VCMI_ANDROID // this is awful but it seems using shared libraries on some devices is even worse - if (dllname.find("libVCAI.so") != std::string::npos) { + const std::string filename = libpath.filename().string(); + if (filename == "libVCAI.so") + { getName = (TGetNameFun)VCAI_GetAiName; getAI = (TGetAIFun)VCAI_GetNewAI; - } else if (dllname.find("libStupidAI.so") != std::string::npos) { + } + else if (filename == "libStupidAI.so") + { getName = (TGetNameFun)StupidAI_GetAiName; getAI = (TGetAIFun)StupidAI_GetNewBattleAI; - } else if (dllname.find("libBattleAI.so") != std::string::npos) { + } + else if (filename == "libBattleAI.so") + { getName = (TGetNameFun)BattleAI_GetAiName; getAI = (TGetAIFun)BattleAI_GetNewBattleAI; - } else { - throw std::runtime_error("Don't know what to do with " + dllname + " and method " + methodName); } -#else - -#ifdef _WIN32 - HINSTANCE dll = LoadLibraryA(dllname.c_str()); + else + throw std::runtime_error("Don't know what to do with " + libpath.string() + " and method " + methodName); +#else // !VCMI_ANDROID +#ifdef VCMI_WINDOWS + HMODULE dll = LoadLibraryW(libpath.c_str()); if (dll) { - getName = (TGetNameFun)GetProcAddress(dll,"GetAiName"); - getAI = (TGetAIFun)GetProcAddress(dll,methodName.c_str()); + getName = (TGetNameFun)GetProcAddress(dll, "GetAiName"); + getAI = (TGetAIFun)GetProcAddress(dll, methodName.c_str()); } -#else - void *dll = dlopen(dllname.c_str(), RTLD_LOCAL | RTLD_LAZY); +#else // !VCMI_WINDOWS + void *dll = dlopen(libpath.string().c_str(), RTLD_LOCAL | RTLD_LAZY); if (dll) { - getName = (TGetNameFun)dlsym(dll,"GetAiName"); - getAI = (TGetAIFun)dlsym(dll,methodName.c_str()); + getName = (TGetNameFun)dlsym(dll, "GetAiName"); + getAI = (TGetAIFun)dlsym(dll, methodName.c_str()); } else logGlobal->errorStream() << "Error: " << dlerror(); -#endif +#endif // VCMI_WINDOWS if (!dll) { - logGlobal->errorStream() << "Cannot open dynamic library ("<errorStream() << "Cannot open dynamic library ("<errorStream() << dllname << " does not export method " << methodName; -#ifdef _WIN32 + logGlobal->errorStream() << libpath << " does not export method " << methodName; +#ifdef VCMI_WINDOWS FreeLibrary(dll); #else dlclose(dll); #endif throw std::runtime_error("Cannot find method " + methodName); } - -#endif // __ANDROID__ +#endif // VCMI_ANDROID getName(temp); logGlobal->infoStream() << "Loaded " << temp; @@ -108,13 +111,13 @@ shared_ptr createAny(std::string dllname, std::string methodName) } template -shared_ptr createAnyAI(std::string dllname, std::string methodName) +shared_ptr createAnyAI(std::string dllname, const std::string& methodName) { - logGlobal->infoStream() << "Opening " << dllname; - std::string filename = VCMIDirs::get().libraryName(dllname); - - auto ret = createAny(VCMIDirs::get().libraryPath() + "/AI/" + filename, methodName); - ret->dllName = dllname; + logGlobal->infoStream() << "Opening " << dllname; + const boost::filesystem::path filePath = + VCMIDirs::get().libraryPath() / "AI" / VCMIDirs::get().libraryName(dllname); + auto ret = createAny(filePath, methodName); + ret->dllName = std::move(dllname); return ret; } diff --git a/lib/CThreadHelper.cpp b/lib/CThreadHelper.cpp index 8f237b6f8..cbbeeb292 100644 --- a/lib/CThreadHelper.cpp +++ b/lib/CThreadHelper.cpp @@ -1,9 +1,9 @@ #include "StdInc.h" #include "CThreadHelper.h" -#ifdef _WIN32 +#ifdef VCMI_WINDOWS #include -#elif !defined(__APPLE__) +#elif !defined(VCMI_APPLE) #include #endif /* @@ -49,7 +49,7 @@ void CThreadHelper::processTasks() // NOTE: on *nix string will be trimmed to 16 symbols void setThreadName(const std::string &name) { -#ifdef _WIN32 +#ifdef VCMI_WINDOWS #ifndef __GNUC__ //follows http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx const DWORD MS_VC_EXCEPTION=0x406D1388; diff --git a/lib/CondSh.h b/lib/CondSh.h index fe9cac8a2..1ec163571 100644 --- a/lib/CondSh.h +++ b/lib/CondSh.h @@ -17,50 +17,48 @@ template struct CondSh boost::condition_variable cond; boost::mutex mx; - CondSh() - {} - - CondSh(T t) - { - data = t; - } + CondSh() {} + CondSh(T t) : data(t) {} + // set data void set(T t) { boost::unique_lock lock(mx); - data=t; + data = t; } - void setn(T t) //set data and notify + // set data and notify + void setn(T t) { - { - boost::unique_lock lock(mx); - data=t; - } + set(t); cond.notify_all(); }; - T get() //get stored value + // get stored value + T get() { boost::unique_lock lock(mx); return data; } - void waitWhileTrue() //waits until data is set to false + // waits until data is set to false + void waitWhileTrue() { boost::unique_lock un(mx); while(data) cond.wait(un); } - void waitWhile(const T &t) //waits while data is set to arg + // waits while data is set to arg + void waitWhile(const T & t) { boost::unique_lock un(mx); while(data == t) cond.wait(un); } - void waitUntil(const T &t) //waits until data is set to arg + // waits until data is set to arg + void waitUntil(const T & t) { boost::unique_lock un(mx); while(data != t) diff --git a/lib/Connection.cpp b/lib/Connection.cpp index 45f423861..949e3e689 100644 --- a/lib/Connection.cpp +++ b/lib/Connection.cpp @@ -347,7 +347,7 @@ void CSaveFile::putMagicBytes( const std::string &text ) write(text.c_str(), text.length()); } -CLoadFile::CLoadFile(const std::string &fname, int minimalVersion /*= version*/) +CLoadFile::CLoadFile(const boost::filesystem::path & fname, int minimalVersion /*= version*/) { registerTypes(*this); openNextFile(fname, minimalVersion); @@ -363,33 +363,33 @@ int CLoadFile::read(void * data, unsigned size) return size; } -void CLoadFile::openNextFile(const std::string &fname, int minimalVersion) +void CLoadFile::openNextFile(const boost::filesystem::path & fname, int minimalVersion) { assert(!reverseEndianess); assert(minimalVersion <= version); try { - fName = fname; - sfile = make_unique(fname, std::ios::binary); + fName = fname.string(); + sfile = make_unique(fname, std::ios::binary); sfile->exceptions(std::ifstream::failbit | std::ifstream::badbit); //we throw a lot anyway if(!(*sfile)) - THROW_FORMAT("Error: cannot open to read %s!", fname); + THROW_FORMAT("Error: cannot open to read %s!", fName); //we can read char buffer[4]; sfile->read(buffer, 4); if(std::memcmp(buffer,"VCMI",4)) - THROW_FORMAT("Error: not a VCMI file(%s)!", fname); + THROW_FORMAT("Error: not a VCMI file(%s)!", fName); *this >> fileVersion; if(fileVersion < minimalVersion) - THROW_FORMAT("Error: too old file format (%s)!", fname); + THROW_FORMAT("Error: too old file format (%s)!", fName); if(fileVersion > version) { - logGlobal->warnStream() << boost::format("Warning format version mismatch: found %d when current is %d! (file %s)\n") % fileVersion % version % fname; + logGlobal->warnStream() << boost::format("Warning format version mismatch: found %d when current is %d! (file %s)\n") % fileVersion % version % fName; auto versionptr = (char*)&fileVersion; std::reverse(versionptr, versionptr + 4); @@ -401,7 +401,7 @@ void CLoadFile::openNextFile(const std::string &fname, int minimalVersion) reverseEndianess = true; } else - THROW_FORMAT("Error: too new file format (%s)!", fname); + THROW_FORMAT("Error: too new file format (%s)!", fName); } } catch(...) diff --git a/lib/Connection.h b/lib/Connection.h index 2b976d26b..ddcebc062 100644 --- a/lib/Connection.h +++ b/lib/Connection.h @@ -1530,17 +1530,17 @@ class DLL_LINKAGE CLoadFile public: std::string fName; - unique_ptr sfile; + unique_ptr sfile; - CLoadFile(const std::string &fname, int minimalVersion = version); //throws! + CLoadFile(const boost::filesystem::path & fname, int minimalVersion = version); //throws! ~CLoadFile(); int read(void * data, unsigned size); //throws! - void openNextFile(const std::string &fname, int minimalVersion); //throws! + void openNextFile(const boost::filesystem::path & fname, int minimalVersion); //throws! void clear(); void reportState(CLogger * out); - void checkMagicBytes(const std::string &text); + void checkMagicBytes(const std::string & text); }; class DLL_LINKAGE CLoadIntegrityValidator : public CISer diff --git a/lib/VCMIDirs.cpp b/lib/VCMIDirs.cpp index 35c6ad47c..2ae9df1fc 100644 --- a/lib/VCMIDirs.cpp +++ b/lib/VCMIDirs.cpp @@ -1,6 +1,3 @@ -#include "StdInc.h" -#include "VCMIDirs.h" - /* * VCMIDirs.cpp, part of VCMI engine * @@ -11,216 +8,504 @@ * */ -static VCMIDirs VCMIDirsGlobal; +#include "StdInc.h" +#include "VCMIDirs.h" -VCMIDirs::VCMIDirs() +namespace bfs = boost::filesystem; + +bfs::path IVCMIDirs::userSavePath() const { return userDataPath() / "Saves"; } + +void IVCMIDirs::init() { - // initialize local directory and create folders to which VCMI needs write access - boost::filesystem::create_directory(userDataPath()); - boost::filesystem::create_directory(userCachePath()); - boost::filesystem::create_directory(userConfigPath()); - boost::filesystem::create_directory(userSavePath()); + // TODO: Log errors + bfs::create_directory(userDataPath()); + bfs::create_directory(userCachePath()); + bfs::create_directory(userConfigPath()); + bfs::create_directory(userSavePath()); } -VCMIDirs & VCMIDirs::get() +#ifdef VCMI_WINDOWS + +#include +#include +#include + +// Generates script file named _temp.bat in 'to' directory and runs it +// Script will: +// - Wait util 'exeName' ends. +// - Copy all files from 'from' to 'to' +// - Ask user to replace files existed in 'to'. +// - Run 'exeName' +// - Delete itself. +bool StartBatchCopyDataProgram( + const bfs::path& from, const bfs::path& to, const bfs::path& exeName, + const bfs::path& currentPath = bfs::current_path()) { - return VCMIDirsGlobal; + static const char base[] = + "@echo off" "\n" + "echo Preparing to move VCMI data system." "\n" + + ":CLIENT_RUNNING_LOOP" "\n" + "TASKLIST | FIND /I %1% > nul" "\n" + "IF ERRORLEVEL 1 (" "\n" + "GOTO CLIENT_NOT_RUNNING" "\n" + ") ELSE (" "\n" + "echo %1% is still running..." "\n" + "echo Waiting until process ends..." "\n" + "ping 1.1.1.1 -n 1 -w 3000 > nul" "\n" // Sleep ~3 seconds. I love Windows :) + "goto :CLIENT_RUNNING_LOOP" "\n" + ")" "\n" + + ":CLIENT_NOT_RUNNING" "\n" + "echo %1% turned off..." "\n" + "echo Attempt to move datas." "\n" + "echo From: %2%" "\n" + "echo To: %4%" "\n" + "echo Please resolve any conflicts..." "\n" + "move /-Y %3% %4%" "\n" // Move all files from %3% to %4%. + // /-Y ask what to do when file exists in %4% + ":REMOVE_OLD_DIR" "\n" + "rd %2% || rem" "\n" // Remove empty directory. Sets error flag if fail. + "IF ERRORLEVEL 145 (" "\n" // Directory not empty + "echo Directory %2% is not empty." "\n" + "echo Please move rest of files manually now." "\n" + "pause" "\n" // Press any key to continue... + "goto REMOVE_OLD_DIR" "\n" + ")" "\n" + "echo Game data updated succefully." "\n" + "echo Please update your shortcuts." "\n" + "echo Press any key to start a game . . ." "\n" + "pause > nul" "\n" + "%5%" "\n" + "del \"%%~f0\"&exit" "\n" // Script deletes itself + ; + + const auto startGameString = + bfs::equivalent(currentPath, from) ? + (boost::format("start \"\" %1%") % (to / exeName)) : // Start game in new path. + (boost::format("start \"\" /D %1% %2%") % currentPath % (to / exeName)); // Start game in 'currentPath" + + const bfs::path bathFilename = to / "_temp.bat"; + bfs::ofstream bathFile(bathFilename, bfs::ofstream::trunc | bfs::ofstream::out); + if (!bathFile.is_open()) + return false; + bathFile << (boost::format(base) % exeName % from % (from / "*.*") % to % startGameString.str()).str(); + bathFile.close(); + + std::system(("start \"Updating VCMI datas\" /D \"" + to.string() + "\" \"" + bathFilename.string() + '\"').c_str()); + // start won't block std::system + // /D start bat in other directory insteand of current directory. + + return true; } -//FIXME: find way to at least decrease size of this ifdef (along with cleanup in CMake) -#if defined(_WIN32) - -std::string VCMIDirs::userCachePath() const +class VCMIDirsWIN32 : public IVCMIDirs { - return userDataPath(); + public: + boost::filesystem::path userDataPath() const override; + boost::filesystem::path userCachePath() const override; + boost::filesystem::path userConfigPath() const override; + + std::vector dataPaths() const override; + + boost::filesystem::path clientPath() const override; + boost::filesystem::path serverPath() const override; + + boost::filesystem::path libraryPath() const override; + boost::filesystem::path binaryPath() const override; + + std::string libraryName(const std::string& basename) const override; + + std::string genHelpString() const override; + + void init() override; + protected: + boost::filesystem::path oldUserDataPath() const; + boost::filesystem::path oldUserSavePath() const; +}; + +void VCMIDirsWIN32::init() +{ + // Call base (init dirs) + IVCMIDirs::init(); + + // Moves one directory (from) contents to another directory (to) + // Shows user the "moving file dialog" and ask to resolve conflits. + // If necessary updates current directory. + auto moveDirIfExists = [](const bfs::path& from, const bfs::path& to) -> bool + { + if (!bfs::is_directory(from)) + return true; // Nothing to do here. Flies away. + + if (bfs::is_empty(from)) + { + if (bfs::current_path() == from) + bfs::current_path(to); + + bfs::remove(from); + return true; // Nothing to do here. Flies away. + } + + if (!bfs::is_directory(to)) + { + // IVCMIDirs::init() should create all destination directories. + // TODO: Log fact, that we shouldn't be here. + bfs::create_directory(to); + } + + // Why the hell path strings should be end with double null :/ + auto makeDoubleNulled = [](const bfs::path& path) -> std::unique_ptr + { + const std::wstring& pathStr = path.native(); + std::unique_ptr result(new wchar_t[pathStr.length() + 2]); + + size_t i = 0; + for (const wchar_t ch : pathStr) + result[i++] = ch; + result[i++] = L'\0'; + result[i++] = L'\0'; + + return result; + }; + + auto fromDNulled = makeDoubleNulled(from / L"*.*"); + auto toDNulled = makeDoubleNulled(to); + + SHFILEOPSTRUCTW fileOp; + fileOp.hwnd = GetConsoleWindow(); + fileOp.wFunc = FO_MOVE; + fileOp.pFrom = fromDNulled.get(); + fileOp.pTo = toDNulled.get(); + fileOp.fFlags = 0; + fileOp.hNameMappings = nullptr; + fileOp.lpszProgressTitle = nullptr; + + const int errorCode = SHFileOperationW(&fileOp); + if (errorCode != 0) // TODO: Log error. User should try to move files. + return false; + else if (fileOp.fAnyOperationsAborted) // TODO: Log warn. User aborted operation. User should move files. + return false; + else if (!bfs::is_empty(from)) // TODO: Log warn. Some files not moved. User should try to move files. + return false; + + if (bfs::current_path() == from) + bfs::current_path(to); + + // TODO: Log fact that we moved files succefully. + bfs::remove(from); + return true; + }; + + // Retrieves the fully qualified path for the file that contains the specified module. + // The module must have been loaded by the current process. + // If this parameter is nullptr, retrieves the path of the executable file of the current process. + auto getModulePath = [](HMODULE hModule) -> bfs::path + { + wchar_t exePathW[MAX_PATH]; + DWORD nSize = GetModuleFileNameW(hModule, exePathW, MAX_PATH); + DWORD error = GetLastError(); + // WARN: Windows XP don't set ERROR_INSUFFICIENT_BUFFER error. + if (nSize != 0 && error != ERROR_INSUFFICIENT_BUFFER) + return bfs::path(std::wstring(exePathW, nSize)); + // TODO: Error handling + return bfs::path(); + }; + + // Moves one directory contents to another directory + // Shows user the "moving file dialog" and ask to resolve conflicts. + // It takes into account that 'from' path can contain current executable. + // If necessary closes program and starts update script. + auto advancedMoveDirIfExists = [getModulePath, moveDirIfExists](const bfs::path& from, const bfs::path& to) -> bool + { + const bfs::path executablePath = getModulePath(nullptr); + + // VCMI cann't determine executable path. + // Use standard way to move directory and exit function. + if (executablePath.empty()) + return moveDirIfExists(from, to); + + const bfs::path executableName = executablePath.filename(); + + // Current executabl isn't in 'from' path. + // Use standard way to move directory and exit function. + if (!bfs::equivalent(executablePath, from / executableName)) + return moveDirIfExists(from, to); + + // Try standard way to move directory. + // I don't know how other systems, but Windows 8.1 allow to move running executable. + if (moveDirIfExists(from, to)) + return true; + + // Start copying script and exit program. + if (StartBatchCopyDataProgram(from, to, executableName)) + exit(ERROR_SUCCESS); + + // Everything failed :C + return false; + }; + + moveDirIfExists(oldUserSavePath(), userSavePath()); + advancedMoveDirIfExists(oldUserDataPath(), userDataPath()); } -std::string VCMIDirs::userConfigPath() const +bfs::path VCMIDirsWIN32::userDataPath() const { - return userDataPath() + "/config"; -} + wchar_t profileDir[MAX_PATH]; -std::string VCMIDirs::userSavePath() const -{ - return userDataPath() + "/Games"; -} - -std::string VCMIDirs::userDataPath() const -{ - const std::string homeDir = std::getenv("userprofile"); - return homeDir + "\\vcmi"; - //return dataPaths()[0]; -} - -std::string VCMIDirs::libraryPath() const -{ + if (SHGetSpecialFolderPathW(nullptr, profileDir, CSIDL_MYDOCUMENTS, FALSE) != FALSE) + return bfs::path(profileDir) / "My Games\\vcmi"; + return "."; } -std::string VCMIDirs::clientPath() const +bfs::path VCMIDirsWIN32::oldUserDataPath() const { - return libraryPath() + "\\" + "VCMI_client.exe"; + wchar_t profileDir[MAX_PATH]; + + if (SHGetSpecialFolderPathW(nullptr, profileDir, CSIDL_PROFILE, FALSE) == FALSE) // WinAPI way failed + { +#if defined(_MSC_VER) && _MSC_VER >= 1700 + wchar_t* buffer; + size_t bufferSize; + errno_t result = _wdupenv_s(&buffer, &bufferSize, L"userprofile"); + if (result == 0) + { + bfs::path result(std::wstring(buffer, bufferSize)); + free(buffer); + return result; + } +#else + const char* profileDirA; + if (profileDirA = std::getenv("userprofile")) // STL way succeed + return bfs::path(profileDirA) / "vcmi"; +#endif + else + return "."; // Every thing failed, return current directory. + } + else + return bfs::path(profileDir) / "vcmi"; + + //return dataPaths()[0] ???; +} +bfs::path VCMIDirsWIN32::oldUserSavePath() const { return userDataPath() / "Games"; } + +bfs::path VCMIDirsWIN32::userCachePath() const { return userDataPath(); } +bfs::path VCMIDirsWIN32::userConfigPath() const { return userDataPath() / "config"; } + +std::vector VCMIDirsWIN32::dataPaths() const +{ + return std::vector(1, bfs::path(".")); } -std::string VCMIDirs::serverPath() const +bfs::path VCMIDirsWIN32::clientPath() const { return binaryPath() / "VCMI_client.exe"; } +bfs::path VCMIDirsWIN32::serverPath() const { return binaryPath() / "VCMI_server.exe"; } + +bfs::path VCMIDirsWIN32::libraryPath() const { return "."; } +bfs::path VCMIDirsWIN32::binaryPath() const { return "."; } + +std::string VCMIDirsWIN32::genHelpString() const { - return libraryPath() + "\\" + "VCMI_server.exe"; + + std::vector tempVec; + for (const bfs::path& path : dataPaths()) + tempVec.push_back(path.string()); + std::string gdStringA = boost::algorithm::join(tempVec, ";"); + + + return + " game data: " + gdStringA + "\n" + " libraries: " + libraryPath().string() + "\n" + " server: " + serverPath().string() + "\n" + "\n" + " user data: " + userDataPath().string() + "\n" + " user cache: " + userCachePath().string() + "\n" + " user config: " + userConfigPath().string() + "\n" + " user saves: " + userSavePath().string() + "\n"; // Should end without new-line? } -std::vector VCMIDirs::dataPaths() const +std::string VCMIDirsWIN32::libraryName(const std::string& basename) const { return basename + ".dll"; } +#elif defined(VCMI_UNIX) +class IVCMIDirsUNIX : public IVCMIDirs { - return std::vector(1, "."); + public: + boost::filesystem::path clientPath() const override; + boost::filesystem::path serverPath() const override; + + std::string genHelpString() const override; +}; + +bfs::path IVCMIDirsUNIX::clientPath() const { return binaryPath() / "vcmiclient"; } +bfs::path IVCMIDirsUNIX::serverPath() const { return binaryPath() / "vcmiserver"; } + +std::string IVCMIDirsUNIX::genHelpString() const +{ + std::vector tempVec; + for (const bfs::path& path : dataPaths()) + tempVec.push_back(path.string()); + std::string gdStringA = boost::algorithm::join(tempVec, ":"); + + + return + " game data: " + gdStringA + "\n" + " libraries: " + libraryPath().string() + "\n" + " server: " + serverPath().string() + "\n" + "\n" + " user data: " + userDataPath().string() + "\n" + " user cache: " + userCachePath().string() + "\n" + " user config: " + userConfigPath().string() + "\n" + " user saves: " + userSavePath().string() + "\n"; // Should end without new-line? } -std::string VCMIDirs::libraryName(std::string basename) const +#ifdef VCMI_APPLE +class VCMIDirsOSX : public IVCMIDirsUNIX { - return basename + ".dll"; + public: + boost::filesystem::path userDataPath() const override; + boost::filesystem::path userCachePath() const override; + boost::filesystem::path userConfigPath() const override; + + std::vector dataPaths() const override; + + boost::filesystem::path libraryPath() const override; + boost::filesystem::path binaryPath() const override; + + std::string libraryName(const std::string& basename) const override; + + void init() override; +}; + +void VCMIDirsOSX::init() +{ + // Call base (init dirs) + IVCMIDirsUNIX::init(); + + auto moveDirIfExists = [](const bfs::path& from, const bfs::path& to) + { + if (!bfs::is_directory(from)) + return; // Nothing to do here. Flies away. + + if (bfs::is_empty(from)) + { + bfs::remove(from); + return; // Nothing to do here. Flies away. + } + + if (!bfs::is_directory(to)) + { + // IVCMIDirs::init() should create all destination directories. + // TODO: Log fact, that we shouldn't be here. + bfs::create_directory(to); + } + + for (bfs::directory_iterator file(from); file != bfs::directory_iterator(); ++file) + { + const boost::filesystem::path& srcFilePath = file->path(); + const boost::filesystem::path dstFilePath = to / srcFilePath.filename(); + + // TODO: Aplication should ask user what to do when file exists: + // replace/ignore/stop process/replace all/ignore all + if (!boost::filesystem::exists(dstFilePath)) + bfs::rename(srcFilePath, dstFilePath); + } + + if (!bfs::is_empty(from)); // TODO: Log warn. Some files not moved. User should try to move files. + else + bfs::remove(from); + }; + + moveDirIfExists(userDataPath() / "Games", userSavePath()); } -#elif defined(__APPLE__) - -std::string VCMIDirs::userCachePath() const -{ - return userDataPath(); -} - -std::string VCMIDirs::userConfigPath() const -{ - return userDataPath() + "/config"; -} - -std::string VCMIDirs::userSavePath() const -{ - return userDataPath() + "/Games"; -} - -std::string VCMIDirs::userDataPath() const +bfs::path VCMIDirsOSX::userDataPath() 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") != nullptr ) - home_dir = getenv("HOME"); - return boost::filesystem::path(home_dir + "/Library/Application Support/vcmi").string(); + const char* homeDir = getenv("HOME"); // Should be std::getenv? + if (homeDir == nullptr) + homeDir = "."; + return bfs::path(homeDir) / "Library" / "Application Support" / "vcmi"; +} +bfs::path VCMIDirsOSX::userCachePath() const { return userDataPath(); } +bfs::path VCMIDirsOSX::userConfigPath() const { return userDataPath() / "config"; } + +std::vector VCMIDirsOSX::dataPaths() const +{ + return std::vector(1, "../Data"); } -std::string VCMIDirs::libraryPath() const +bfs::path VCMIDirsOSX::libraryPath() const { return "."; } +bfs::path VCMIDirsOSX::binaryPath() const { return "."; } + +std::string libraryName(const std::string& basename) { return "lib" + basename + ".dylib"; } +#elif defined(VCMI_LINUX) +class VCMIDirsLinux : public IVCMIDirsUNIX { - return "."; +public: + boost::filesystem::path userDataPath() const override; + boost::filesystem::path userCachePath() const override; + boost::filesystem::path userConfigPath() const override; + + std::vector dataPaths() const override; + + boost::filesystem::path libraryPath() const override; + boost::filesystem::path binaryPath() const override; + + std::string libraryName(const std::string& basename) const override; +}; + +bfs::path VCMIDirsLinux::userDataPath() const +{ + // $XDG_DATA_HOME, default: $HOME/.local/share + const char* homeDir; + if ((homeDir = getenv("XDG_DATA_HOME"))) + return homeDir; + else if ((homeDir = getenv("HOME"))) + return bfs::path(homeDir) / ".local" / "share" / "vcmi"; + else + return "."; +} +bfs::path VCMIDirsLinux::userCachePath() const +{ + // $XDG_CACHE_HOME, default: $HOME/.cache + const char* tempResult; + if ((tempResult = getenv("XDG_CACHE_HOME"))) + return bfs::path(tempResult) / "vcmi"; + else if ((tempResult = getenv("HOME"))) + return bfs::path(tempResult) / ".cache" / "vcmi"; + else + return "."; +} +bfs::path VCMIDirsLinux::userConfigPath() const +{ + // $XDG_CONFIG_HOME, default: $HOME/.config + const char* tempResult; + if ((tempResult = getenv("XDG_CONFIG_HOME"))) + return bfs::path(tempResult) / "vcmi"; + else if ((tempResult = getenv("HOME"))) + return bfs::path(tempResult) / ".config" / "vcmi"; + else + return "."; } -std::string VCMIDirs::clientPath() const +std::vector VCMIDirsLinux::dataPaths() const { - return "./vcmiclient"; -} + // $XDG_DATA_DIRS, default: /usr/local/share/:/usr/share/ -std::string VCMIDirs::serverPath() const -{ - return "./vcmiserver"; -} - -std::vector VCMIDirs::dataPaths() const -{ - return std::vector(1, "../Data"); -} - -std::string VCMIDirs::libraryName(std::string basename) const -{ - return "lib" + basename + ".dylib"; -} - -#else - -std::string VCMIDirs::libraryName(std::string basename) const -{ - return "lib" + basename + ".so"; -} - -std::string VCMIDirs::libraryPath() const -{ - return M_LIB_DIR; -} - -std::string VCMIDirs::clientPath() const -{ - return std::string(M_BIN_DIR) + "/" + "vcmiclient"; -} - -std::string VCMIDirs::serverPath() const -{ - return std::string(M_BIN_DIR) + "/" + "vcmiserver"; -} - -// $XDG_DATA_HOME, default: $HOME/.local/share -std::string VCMIDirs::userDataPath() const -{ -#ifdef __ANDROID__ - // on Android HOME will be set to something like /sdcard/data/Android/is.xyz.vcmi/files/ - return std::string(getenv("HOME")); -#else - if (getenv("XDG_DATA_HOME") != nullptr ) - return std::string(getenv("XDG_DATA_HOME")) + "/vcmi"; - if (getenv("HOME") != nullptr ) - return std::string(getenv("HOME")) + "/.local/share" + "/vcmi"; - return "."; -#endif -} - -std::string VCMIDirs::userSavePath() const -{ - return userDataPath() + "/Saves"; -} - -// $XDG_CACHE_HOME, default: $HOME/.cache -std::string VCMIDirs::userCachePath() const -{ -#ifdef __ANDROID__ - return userDataPath() + "/cache"; -#else - if (getenv("XDG_CACHE_HOME") != nullptr ) - return std::string(getenv("XDG_CACHE_HOME")) + "/vcmi"; - if (getenv("HOME") != nullptr ) - return std::string(getenv("HOME")) + "/.cache" + "/vcmi"; - return "."; -#endif -} - -// $XDG_CONFIG_HOME, default: $HOME/.config -std::string VCMIDirs::userConfigPath() const -{ -#ifdef __ANDROID__ - return userDataPath() + "/config"; -#else - if (getenv("XDG_CONFIG_HOME") != nullptr ) - return std::string(getenv("XDG_CONFIG_HOME")) + "/vcmi"; - if (getenv("HOME") != nullptr ) - return std::string(getenv("HOME")) + "/.config" + "/vcmi"; - return "."; -#endif -} - -// $XDG_DATA_DIRS, default: /usr/local/share/:/usr/share/ -std::vector VCMIDirs::dataPaths() const -{ // construct list in reverse. // in specification first directory has highest priority // in vcmi fs last directory has highest priority + std::vector ret; - std::vector ret; -#ifdef __ANDROID__ - ret.push_back(userDataPath()); -#else - if (getenv("HOME") != nullptr ) // compatibility, should be removed after 0.96 - ret.push_back(std::string(getenv("HOME")) + "/.vcmi"); + const char* tempResult; ret.push_back(M_DATA_DIR); - if (getenv("XDG_DATA_DIRS") != nullptr) + if ((tempResult = getenv("XDG_DATA_DIRS")) != nullptr) { - std::string dataDirsEnv = getenv("XDG_DATA_DIRS"); + std::string dataDirsEnv = tempResult; std::vector dataDirs; boost::split(dataDirs, dataDirsEnv, boost::is_any_of(":")); for (auto & entry : boost::adaptors::reverse(dataDirs)) @@ -231,21 +516,61 @@ std::vector VCMIDirs::dataPaths() const ret.push_back("/usr/share/"); ret.push_back("/usr/local/share/"); } -#endif + return ret; } -#endif +bfs::path VCMIDirsLinux::libraryPath() const { return M_LIB_DIR; } +bfs::path VCMIDirsLinux::binaryPath() const { return M_BIN_DIR; } -std::string VCMIDirs::genHelpString() const +std::string VCMIDirsLinux::libraryName(const std::string& basename) const { return "lib" + basename + ".so"; } +#ifdef VCMI_ANDROID +class VCMIDirsAndroid : public VCMIDirsLinux { - return - " game data: " + boost::algorithm::join(dataPaths(), ":") + "\n" + - " libraries: " + libraryPath() + "\n" + - " server: " + serverPath() + "\n" + - "\n" + - " user data: " + userDataPath() + "\n" + - " user cache: " + userCachePath() + "\n" + - " user config: " + userConfigPath() + "\n" + - " user saves: " + userSavePath() + "\n"; +public: + boost::filesystem::path userDataPath() const override; + boost::filesystem::path userCachePath() const override; + boost::filesystem::path userConfigPath() const override; + + std::vector dataPaths() const override; +}; + +// on Android HOME will be set to something like /sdcard/data/Android/is.xyz.vcmi/files/ +bfs::path VCMIDirsAndroid::userDataPath() const { return getenv("HOME"); } +bfs::path VCMIDirsAndroid::userCachePath() const { return userDataPath() / "cache"; } +bfs::path VCMIDirsAndroid::userConfigPath() const { return userDataPath() / "config"; } + +std::vector VCMIDirsAndroid::dataPaths() const +{ + return std::vector(1, userDataPath()); } +#endif // VCMI_ANDROID +#endif // VCMI_APPLE, VCMI_LINUX +#endif // VCMI_WINDOWS, VCMI_UNIX + +// Getters for interfaces are separated for clarity. +namespace VCMIDirs +{ + const IVCMIDirs& get() + { + #ifdef VCMI_WINDOWS + static VCMIDirsWIN32 singleton; + #elif defined(VCMI_ANDROID) + static VCMIDirsAndroid singleton; + #elif defined(VCMI_LINUX) + static VCMIDirsLinux singleton; + #elif defined(VCMI_APPLE) + static VCMIDirsOSX singleton; + #endif + static bool initialized = false; + if (!initialized) + { + std::locale::global(boost::locale::generator().generate("en_US.UTF-8")); + boost::filesystem::path::imbue(std::locale()); + + singleton.init(); + initialized = true; + } + return singleton; + } +} \ No newline at end of file diff --git a/lib/VCMIDirs.h b/lib/VCMIDirs.h index c3f02c56c..fa1e43221 100644 --- a/lib/VCMIDirs.h +++ b/lib/VCMIDirs.h @@ -1,52 +1,58 @@ +/* +* VCMIDirs.h, 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 +* +*/ #pragma once -#include "GameConstants.h" - -/* - * VCMIDirs.h, 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 - * - */ - -/// Where to find the various VCMI files. This is mostly useful for linux. -class DLL_LINKAGE VCMIDirs +class DLL_LINKAGE IVCMIDirs { -public: - VCMIDirs(); + public: + // Path to user-specific data directory + virtual boost::filesystem::path userDataPath() const = 0; - /// get singleton instance - static VCMIDirs & get(); + // Path to "cache" directory, can be used for any non-essential files + virtual boost::filesystem::path userCachePath() const = 0; - /// Path to user-specific data directory - std::string userDataPath() const; + // Path to writeable directory with user configs + virtual boost::filesystem::path userConfigPath() const = 0; - /// Path to "cache" directory, can be used for any non-essential files - std::string userCachePath() const; + // Path to saved games + virtual boost::filesystem::path userSavePath() const; - /// Path to writeable directory with user configs - std::string userConfigPath() const; + // Paths to global system-wide data directories. First items have higher priority + virtual std::vector dataPaths() const = 0; - /// Path to saved games - std::string userSavePath() const; + // Full path to client executable, including server name (e.g. /usr/bin/vcmiclient) + virtual boost::filesystem::path clientPath() const = 0; - /// Paths to global system-wide data directories. First items have higher priority - std::vector dataPaths() const; + // Full path to server executable, including server name (e.g. /usr/bin/vcmiserver) + virtual boost::filesystem::path serverPath() const = 0; - /// Full path to client executable, including server name (e.g. /usr/bin/vcmiclient) - std::string clientPath() const; + // Path where vcmi libraries can be found (in AI and Scripting subdirectories) + virtual boost::filesystem::path libraryPath() const = 0; - /// Full path to server executable, including server name (e.g. /usr/bin/vcmiserver) - std::string serverPath() const; + // Path where vcmi binaries can be found + virtual boost::filesystem::path binaryPath() const = 0; - /// Path where vcmi libraries can be found (in AI and Scripting subdirectories) - std::string libraryPath() const; + // Returns system-specific name for dynamic libraries ( StupidAI => "libStupidAI.so" or "StupidAI.dll") + virtual std::string libraryName(const std::string& basename) const = 0; + // virtual std::string libraryName(const char* basename) const = 0; ? + // virtual std::string libraryName(std::string&& basename) const = 0;? - /// Returns system-specific name for dynamic libraries ( StupidAI => "libStupidAI.so" or "StupidAI.dll") - std::string libraryName(std::string basename) const; - - std::string genHelpString() const; + virtual std::string genHelpString() const = 0; + + // Creates not existed, but required directories. + // Updates directories what change name/path between versions. + // Function called automatically. + virtual void init(); }; + +namespace VCMIDirs +{ + extern DLL_LINKAGE const IVCMIDirs& get(); +} \ No newline at end of file diff --git a/lib/filesystem/CArchiveLoader.cpp b/lib/filesystem/CArchiveLoader.cpp index e1ae5427b..fdebd315a 100644 --- a/lib/filesystem/CArchiveLoader.cpp +++ b/lib/filesystem/CArchiveLoader.cpp @@ -13,9 +13,9 @@ ArchiveEntry::ArchiveEntry() } -CArchiveLoader::CArchiveLoader(const std::string &mountPoint, const std::string & archive): - archive(archive), - mountPoint(mountPoint) +CArchiveLoader::CArchiveLoader(std::string _mountPoint, boost::filesystem::path _archive) : + archive(std::move(_archive)), + mountPoint(std::move(_mountPoint)) { // Open archive file(.snd, .vid, .lod) CFileInputStream fileStream(archive); @@ -25,28 +25,19 @@ CArchiveLoader::CArchiveLoader(const std::string &mountPoint, const std::string return; // Retrieve file extension of archive in uppercase - CFileInfo fileInfo(archive); - std::string ext = fileInfo.getExtension(); - boost::to_upper(ext); + const std::string ext = boost::to_upper_copy(archive.extension().string()); // Init the specific lod container format if(ext == ".LOD" || ext == ".PAC") - { initLODArchive(mountPoint, fileStream); - } else if(ext == ".VID") - { initVIDArchive(mountPoint, fileStream); - } else if(ext == ".SND") - { initSNDArchive(mountPoint, fileStream); - } else - { - throw std::runtime_error("LOD archive format unknown. Cannot deal with " + archive); - } - logGlobal->traceStream() << ext << "Archive loaded, " << entries.size() << " files found"; + throw std::runtime_error("LOD archive format unknown. Cannot deal with " + archive.string()); + + logGlobal->traceStream() << ext << "Archive \""<(filename), 16); @@ -90,7 +81,7 @@ void CArchiveLoader::initVIDArchive(const std::string &mountPoint, CFileInputStr std::set offsets; // Insert entries to list - for(ui32 i = 0; i < totalFiles; i++) + for(ui32 i = 0; i < totalFiles; ++i) { char filename[40]; reader.read(reinterpret_cast(filename), 40); @@ -122,7 +113,7 @@ void CArchiveLoader::initSNDArchive(const std::string &mountPoint, CFileInputStr ui32 totalFiles = reader.readUInt32(); // Insert entries to list - for(ui32 i = 0; i < totalFiles; i++) + for(ui32 i = 0; i < totalFiles; ++i) { char filename[40]; reader.read(reinterpret_cast(filename), 40); diff --git a/lib/filesystem/CArchiveLoader.h b/lib/filesystem/CArchiveLoader.h index e4300a855..7d9b5da78 100644 --- a/lib/filesystem/CArchiveLoader.h +++ b/lib/filesystem/CArchiveLoader.h @@ -55,7 +55,7 @@ public: * * @throws std::runtime_error if the archive wasn't found or if the archive isn't supported */ - explicit CArchiveLoader(const std::string & mountPoint, const std::string & archive); + CArchiveLoader(std::string mountPoint, boost::filesystem::path archive); /// Interface implementation /// @see ISimpleResourceLoader @@ -87,7 +87,7 @@ private: void initSNDArchive(const std::string &mountPoint, CFileInputStream & fileStream); /** The file path to the archive which is scanned and indexed. */ - std::string archive; + boost::filesystem::path archive; std::string mountPoint; diff --git a/lib/filesystem/CFileInfo.cpp b/lib/filesystem/CFileInfo.cpp index 59aef320d..c2347e897 100644 --- a/lib/filesystem/CFileInfo.cpp +++ b/lib/filesystem/CFileInfo.cpp @@ -41,17 +41,17 @@ std::string CFileInfo::getPath() const std::string CFileInfo::getExtension() const { // Get position of file extension dot - size_t dotPos = name.find_last_of("/."); + size_t dotPos = name.find_last_of('.'); - if(dotPos != std::string::npos && name[dotPos] == '.') + if(dotPos != std::string::npos) return name.substr(dotPos); - else - return ""; + + return ""; } std::string CFileInfo::getFilename() const { - size_t found = name.find_last_of("/\\"); + const size_t found = name.find_last_of("/\\"); return name.substr(found + 1); } @@ -60,9 +60,9 @@ std::string CFileInfo::getStem() const std::string rslt = name; // Remove file extension - size_t dotPos = name.find_last_of("/."); + const size_t dotPos = name.find_last_of('.'); - if(dotPos != std::string::npos && name[dotPos] == '.') + if(dotPos != std::string::npos) rslt.erase(dotPos); return rslt; @@ -70,18 +70,19 @@ std::string CFileInfo::getStem() const std::string CFileInfo::getBaseName() const { - size_t begin = name.find_last_of("/"); - size_t end = name.find_last_of("/."); - - if(end != std::string::npos && name[end] == '/') - end = std::string::npos; + size_t begin = name.find_last_of("/\\"); + size_t end = name.find_last_of("."); if(begin == std::string::npos) begin = 0; else - begin++; + ++begin; + + if (end < begin) + end = std::string::npos; - return name.substr(begin, end - begin); + size_t len = (end == std::string::npos ? std::string::npos : end - begin); + return name.substr(begin, len); } EResType::Type CFileInfo::getType() const diff --git a/lib/filesystem/CFileInputStream.cpp b/lib/filesystem/CFileInputStream.cpp index 66b70e11d..758948325 100644 --- a/lib/filesystem/CFileInputStream.cpp +++ b/lib/filesystem/CFileInputStream.cpp @@ -3,7 +3,7 @@ #include "CFileInfo.h" -CFileInputStream::CFileInputStream(const std::string & file, si64 start, si64 size) +CFileInputStream::CFileInputStream(const boost::filesystem::path & file, si64 start, si64 size) { open(file, start, size); } @@ -18,14 +18,12 @@ CFileInputStream::~CFileInputStream() fileStream.close(); } -void CFileInputStream::open(const std::string & file, si64 start, si64 size) +void CFileInputStream::open(const boost::filesystem::path & file, si64 start, si64 size) { - fileStream.open(file.c_str(), std::ios::in | std::ios::binary); + fileStream.open(file, std::ios::in | std::ios::binary); if (fileStream.fail()) - { - throw std::runtime_error("File " + file + " isn't available."); - } + throw std::runtime_error("File " + file.string() + " isn't available."); dataStart = start; dataSize = size; diff --git a/lib/filesystem/CFileInputStream.h b/lib/filesystem/CFileInputStream.h index a6d1d74cf..31e57f069 100644 --- a/lib/filesystem/CFileInputStream.h +++ b/lib/filesystem/CFileInputStream.h @@ -25,7 +25,7 @@ public: * * @see CFileInputStream::open */ - CFileInputStream(const std::string & file, si64 start=0, si64 size=0); + CFileInputStream(const boost::filesystem::path & file, si64 start = 0, si64 size = 0); /** * C-tor. Opens the specified file. @@ -88,11 +88,11 @@ private: * * @throws std::runtime_error if file wasn't found */ - void open(const std::string & file, si64 start, si64 size); + void open(const boost::filesystem::path & file, si64 start, si64 size); si64 dataStart; si64 dataSize; /** Native c++ input file stream object. */ - std::ifstream fileStream; + boost::filesystem::ifstream fileStream; }; diff --git a/lib/filesystem/CFilesystemLoader.cpp b/lib/filesystem/CFilesystemLoader.cpp index a35c7d892..0704c8a06 100644 --- a/lib/filesystem/CFilesystemLoader.cpp +++ b/lib/filesystem/CFilesystemLoader.cpp @@ -4,9 +4,11 @@ #include "CFileInfo.h" #include "CFileInputStream.h" -CFilesystemLoader::CFilesystemLoader(const std::string &mountPoint, const std::string & baseDirectory, size_t depth, bool initial): - baseDirectory(baseDirectory), - mountPoint(mountPoint), +namespace bfs = boost::filesystem; + +CFilesystemLoader::CFilesystemLoader(std::string _mountPoint, bfs::path baseDirectory, size_t depth, bool initial): + baseDirectory(std::move(baseDirectory)), + mountPoint(std::move(_mountPoint)), fileList(listFiles(mountPoint, depth, initial)) { logGlobal->traceStream() << "Filesystem loaded, " << fileList.size() << " files found"; @@ -16,7 +18,7 @@ std::unique_ptr CFilesystemLoader::load(const ResourceID & resourc { assert(fileList.count(resourceName)); - std::unique_ptr stream(new CFileInputStream(baseDirectory + '/' + fileList.at(resourceName))); + std::unique_ptr stream(new CFileInputStream(baseDirectory / fileList.at(resourceName))); return stream; } @@ -34,7 +36,7 @@ boost::optional CFilesystemLoader::getResourceName(const ResourceID { assert(existsResource(resourceName)); - return baseDirectory + '/' + fileList.at(resourceName); + return (baseDirectory / fileList.at(resourceName)).string(); } std::unordered_set CFilesystemLoader::getFilteredFiles(std::function filter) const @@ -45,7 +47,8 @@ std::unordered_set CFilesystemLoader::getFilteredFiles(std::function { if (filter(file.first)) foundID.insert(file.first); - } return foundID; + } + return foundID; } bool CFilesystemLoader::createResource(std::string filename, bool update) @@ -65,7 +68,7 @@ bool CFilesystemLoader::createResource(std::string filename, bool update) if (!update) { - std::ofstream newfile (baseDirectory + "/" + filename); + bfs::ofstream newfile(baseDirectory / filename); if (!newfile.good()) return false; } @@ -73,49 +76,72 @@ bool CFilesystemLoader::createResource(std::string filename, bool update) return true; } -std::unordered_map CFilesystemLoader::listFiles(const std::string &mountPoint, size_t depth, bool initial) const +std::unordered_map CFilesystemLoader::listFiles(const std::string &mountPoint, size_t depth, bool initial) const { - std::set initialTypes; - initialTypes.insert(EResType::DIRECTORY); - initialTypes.insert(EResType::TEXT); - initialTypes.insert(EResType::ARCHIVE_LOD); - initialTypes.insert(EResType::ARCHIVE_VID); - initialTypes.insert(EResType::ARCHIVE_SND); - initialTypes.insert(EResType::ARCHIVE_ZIP); + static const EResType::Type initArray[] = { + EResType::DIRECTORY, + EResType::TEXT, + EResType::ARCHIVE_LOD, + EResType::ARCHIVE_VID, + EResType::ARCHIVE_SND, + EResType::ARCHIVE_ZIP }; + static const std::set initialTypes(initArray, initArray + ARRAY_COUNT(initArray)); - assert(boost::filesystem::is_directory(baseDirectory)); - std::unordered_map fileList; + assert(bfs::is_directory(baseDirectory)); + std::unordered_map fileList; - std::vector path;//vector holding relative path to our file + std::vector path; //vector holding relative path to our file - boost::filesystem::recursive_directory_iterator enddir; - boost::filesystem::recursive_directory_iterator it(baseDirectory, boost::filesystem::symlink_option::recurse); + bfs::recursive_directory_iterator enddir; + bfs::recursive_directory_iterator it(baseDirectory, bfs::symlink_option::recurse); for(; it != enddir; ++it) { EResType::Type type; - if (boost::filesystem::is_directory(it->status())) + if (bfs::is_directory(it->status())) { - path.resize(it.level()+1); - path.back() = it->path().leaf().string(); + path.resize(it.level() + 1); + path.back() = it->path().filename(); // don't iterate into directory if depth limit reached it.no_push(depth <= it.level()); type = EResType::DIRECTORY; } else - type = EResTypeHelper::getTypeFromExtension(boost::filesystem::extension(*it)); + type = EResTypeHelper::getTypeFromExtension(it->path().extension().string()); if (!initial || vstd::contains(initialTypes, type)) { //reconstruct relative filename (not possible via boost AFAIK) - std::string filename; - for (size_t i=0; ipath().leaf().string(); + bfs::path filename; + const size_t iterations = std::min((size_t)it.level(), path.size()); + if (iterations) + { + filename = path.front(); + for (size_t i = 1; i < iterations; ++i) + filename /= path[i]; + filename /= it->path().filename(); + } + else + filename = it->path().filename(); - fileList[ResourceID(mountPoint + filename, type)] = filename; + std::string resName; + if (bfs::path::preferred_separator != '/') + { + // resource names are using UNIX slashes (/) + resName.reserve(resName.size() + filename.native().size()); + resName = mountPoint; + for (const char c : filename.string()) + if (c != bfs::path::preferred_separator) + resName.push_back(c); + else + resName.push_back('/'); + } + else + resName = mountPoint + filename.string(); + + fileList[ResourceID(resName, type)] = std::move(filename); } } diff --git a/lib/filesystem/CFilesystemLoader.h b/lib/filesystem/CFilesystemLoader.h index 03a597497..e7cfd9a81 100644 --- a/lib/filesystem/CFilesystemLoader.h +++ b/lib/filesystem/CFilesystemLoader.h @@ -30,7 +30,7 @@ public: * * @throws std::runtime_error if the base directory is not a directory or if it is not available */ - explicit CFilesystemLoader(const std::string & mountPoint, const std::string & baseDirectory, size_t depth = 16, bool initial = false); + explicit CFilesystemLoader(std::string mountPoint, boost::filesystem::path baseDirectory, size_t depth = 16, bool initial = false); /// Interface implementation /// @see ISimpleResourceLoader @@ -39,11 +39,11 @@ public: std::string getMountPoint() const override; bool createResource(std::string filename, bool update = false) override; boost::optional getResourceName(const ResourceID & resourceName) const override; - std::unordered_set getFilteredFiles(std::function filter) const; + std::unordered_set getFilteredFiles(std::function filter) const override; private: /** The base directory which is scanned and indexed. */ - std::string baseDirectory; + boost::filesystem::path baseDirectory; std::string mountPoint; @@ -51,7 +51,7 @@ private: * key = ResourceID for resource loader * value = name that can be used to access file */ - std::unordered_map fileList; + std::unordered_map fileList; /** * Returns a list of pathnames denoting the files in the directory denoted by this pathname. @@ -62,5 +62,5 @@ private: * @return a list of pathnames denoting the files and directories in the directory denoted by this pathname * The array will be empty if the directory is empty. Ptr is null if the directory doesn't exist or if it isn't a directory. */ - std::unordered_map listFiles(const std::string &mountPoint, size_t depth, bool initial) const; + std::unordered_map listFiles(const std::string &mountPoint, size_t depth, bool initial) const; }; diff --git a/lib/filesystem/Filesystem.cpp b/lib/filesystem/Filesystem.cpp index ce49e7f9f..c9c9790e5 100644 --- a/lib/filesystem/Filesystem.cpp +++ b/lib/filesystem/Filesystem.cpp @@ -69,7 +69,7 @@ void CFilesystemGenerator::loadDirectory(const std::string &mountPoint, const Js std::string URI = prefix + config["path"].String(); int depth = 16; if (!config["depth"].isNull()) - depth = config["depth"].Float(); + depth = (int)config["depth"].Float(); ResourceID resID(URI, EResType::DIRECTORY); @@ -130,7 +130,7 @@ ISimpleResourceLoader * CResourceHandler::createInitial() auto filename = loader->getResourceName(ID); if (filename) { - auto dir = new CFilesystemLoader(URI + "/", *filename, depth, true); + auto dir = new CFilesystemLoader(URI + '/', *filename, depth, true); initialLoader->addLoader(dir, false); } } diff --git a/lib/int3.h b/lib/int3.h index 41a8dd908..7ac595183 100644 --- a/lib/int3.h +++ b/lib/int3.h @@ -94,11 +94,11 @@ public: } //returns squared distance on Oxy plane (z coord is not used) - si32 dist2dSQ(const int3 & o) const + ui32 dist2dSQ(const int3 & o) const { const si32 dx = (x - o.x); const si32 dy = (y - o.y); - return dx*dx + dy*dy; + return (ui32)(dx*dx) + (ui32)(dy*dy); } //returns distance on Oxy plane (z coord is not used) double dist2d(const int3 & o) const @@ -157,15 +157,17 @@ struct ShashInt3 static const int3 dirs[] = { int3(0,1,0),int3(0,-1,0),int3(-1,0,0),int3(+1,0,0), int3(1,1,0),int3(-1,1,0),int3(1,-1,0),int3(-1,-1,0) }; -//FIXME: make sure it's container and not just any template int3 findClosestTile (Container & container, int3 dest) { - int3 result(-1,-1,-1); + static_assert(std::is_same::value, + "findClosestTile requires container."); + + int3 result(-1, -1, -1); ui32 distance = std::numeric_limits::max(); - for (int3 tile : container) + for (const int3& tile : container) { - ui32 currentDistance = dest.dist2dSQ(tile); + const ui32 currentDistance = dest.dist2dSQ(tile); if (currentDistance < distance) { result = tile; diff --git a/lib/logging/CBasicLogConfigurator.cpp b/lib/logging/CBasicLogConfigurator.cpp index 2db783475..97d0d3d35 100644 --- a/lib/logging/CBasicLogConfigurator.cpp +++ b/lib/logging/CBasicLogConfigurator.cpp @@ -3,11 +3,8 @@ #include "../CConfigHandler.h" -CBasicLogConfigurator::CBasicLogConfigurator(const std::string & filePath, CConsoleHandler * console) : filePath(filePath), - console(console), appendToLogFile(false) -{ - -} +CBasicLogConfigurator::CBasicLogConfigurator(boost::filesystem::path filePath, CConsoleHandler * const console) : + filePath(std::move(filePath)), console(console), appendToLogFile(false) {} void CBasicLogConfigurator::configureDefault() { @@ -21,7 +18,8 @@ void CBasicLogConfigurator::configure() try { const JsonNode & loggingNode = settings["logging"]; - if(loggingNode.isNull()) throw std::runtime_error("Settings haven't been loaded."); + if(loggingNode.isNull()) + throw std::runtime_error("Settings haven't been loaded."); // Configure loggers const JsonNode & loggers = loggingNode["loggers"]; @@ -87,7 +85,7 @@ void CBasicLogConfigurator::configure() logGlobal->infoStream() << "Initialized logging system based on settings successfully."; } -ELogLevel::ELogLevel CBasicLogConfigurator::getLogLevel(const std::string & level) const +ELogLevel::ELogLevel CBasicLogConfigurator::getLogLevel(const std::string & level) { static const std::map levelMap = boost::assign::map_list_of ("trace", ELogLevel::TRACE) @@ -95,18 +93,15 @@ ELogLevel::ELogLevel CBasicLogConfigurator::getLogLevel(const std::string & leve ("info", ELogLevel::INFO) ("warn", ELogLevel::WARN) ("error", ELogLevel::ERROR); + const auto & levelPair = levelMap.find(level); if(levelPair != levelMap.end()) - { return levelPair->second; - } else - { throw std::runtime_error("Log level " + level + " unknown."); - } } -EConsoleTextColor::EConsoleTextColor CBasicLogConfigurator::getConsoleColor(const std::string & colorName) const +EConsoleTextColor::EConsoleTextColor CBasicLogConfigurator::getConsoleColor(const std::string & colorName) { static const std::map colorMap = boost::assign::map_list_of ("default", EConsoleTextColor::DEFAULT) @@ -117,13 +112,10 @@ EConsoleTextColor::EConsoleTextColor CBasicLogConfigurator::getConsoleColor(cons ("white", EConsoleTextColor::WHITE) ("gray", EConsoleTextColor::GRAY) ("teal", EConsoleTextColor::TEAL); + const auto & colorPair = colorMap.find(colorName); if(colorPair != colorMap.end()) - { return colorPair->second; - } else - { throw std::runtime_error("Color " + colorName + " unknown."); - } } diff --git a/lib/logging/CBasicLogConfigurator.h b/lib/logging/CBasicLogConfigurator.h index 4c42f2ea4..498f2a32c 100644 --- a/lib/logging/CBasicLogConfigurator.h +++ b/lib/logging/CBasicLogConfigurator.h @@ -22,7 +22,7 @@ class JsonNode; class DLL_LINKAGE CBasicLogConfigurator { public: - CBasicLogConfigurator(const std::string & filePath, CConsoleHandler * console); + CBasicLogConfigurator(boost::filesystem::path filePath, CConsoleHandler * const console); /// Configures the logging system by parsing the logging settings. It adds the console target and the file target to the global logger. /// Doesn't throw, but logs on success or fault. @@ -30,12 +30,15 @@ public: /// Configures a default logging system by adding the console target and the file target to the global logger. void configureDefault(); - private: - ELogLevel::ELogLevel getLogLevel(const std::string & level) const; - EConsoleTextColor::EConsoleTextColor getConsoleColor(const std::string & colorName) const; + // Gets ELogLevel enum from string. (Should be moved to CLogger as a separate function?) + // Throws: std::runtime_error + static ELogLevel::ELogLevel getLogLevel(const std::string & level); + // Gets EConsoleTextColor enum from strings. (Should be moved to CLogger as a separate function?) + // Throws: std::runtime_error + static EConsoleTextColor::EConsoleTextColor getConsoleColor(const std::string & colorName); - std::string filePath; + boost::filesystem::path filePath; CConsoleHandler * console; bool appendToLogFile; }; diff --git a/lib/logging/CLogger.cpp b/lib/logging/CLogger.cpp index 6832defa7..63fa95b41 100644 --- a/lib/logging/CLogger.cpp +++ b/lib/logging/CLogger.cpp @@ -1,46 +1,51 @@ -#ifdef __ANDROID__ -#include -#endif - #include "StdInc.h" #include "CLogger.h" +#ifdef VCMI_ANDROID +#include + +namespace ELogLevel +{ + int toAndroid(ELogLevel logLevel) + { + switch (logLevel) + { + case TRACE: return ANDROID_LOG_VERBOSE; + case DEBUG: return ANDROID_LOG_DEBUG; + case INFO: return ANDROID_LOG_INFO; + case WARN: return ANDROID_LOG_WARN; + case ERROR: return ANDROID_LOG_ERROR; + default:; + } + return ANDROID_LOG_UNKNOWN; + } +} +#endif + const std::string CLoggerDomain::DOMAIN_GLOBAL = "global"; -CLoggerDomain::CLoggerDomain(const std::string & name) : name(name) +CLoggerDomain::CLoggerDomain(std::string name) : name(std::move(name)) { - if(name.empty()) throw std::runtime_error("Logger domain cannot be empty."); + if (this->name.empty()) + throw std::runtime_error("Logger domain cannot be empty."); } CLoggerDomain CLoggerDomain::getParent() const { - if(isGlobalDomain()) return *this; + if(isGlobalDomain()) + return *this; - size_t pos = name.find_last_of("."); + const size_t pos = name.find_last_of("."); if(pos != std::string::npos) - { return CLoggerDomain(name.substr(0, pos)); - } - else - { - return CLoggerDomain(DOMAIN_GLOBAL); - } + return CLoggerDomain(DOMAIN_GLOBAL); } -bool CLoggerDomain::isGlobalDomain() const -{ - return name == DOMAIN_GLOBAL; -} +bool CLoggerDomain::isGlobalDomain() const { return name == DOMAIN_GLOBAL; } -std::string CLoggerDomain::getName() const -{ - return name; -} +const std::string& CLoggerDomain::getName() const { return name; } -CLoggerStream::CLoggerStream(const CLogger & logger, ELogLevel::ELogLevel level) : logger(logger), level(level), sbuffer(nullptr) -{ - -} +CLoggerStream::CLoggerStream(const CLogger & logger, ELogLevel::ELogLevel level) : logger(logger), level(level), sbuffer(nullptr) {} CLoggerStream::~CLoggerStream() { @@ -67,20 +72,14 @@ CLogger * CLogger::getLogger(const CLoggerDomain & domain) TLockGuardRec _(smx); CLogger * logger = CLogManager::get().getLogger(domain); - if(logger) - { - return logger; - } - else + if(!logger) // Create new logger { logger = new CLogger(domain); if(domain.isGlobalDomain()) - { logger->setLevel(ELogLevel::TRACE); - } CLogManager::get().addLogger(logger); - return logger; } + return logger; } CLogger * CLogger::getGlobalLogger() @@ -102,62 +101,22 @@ CLogger::CLogger(const CLoggerDomain & domain) : domain(domain) } } -void CLogger::trace(const std::string & message) const -{ - log(ELogLevel::TRACE, message); -} +void CLogger::trace(const std::string & message) const { log(ELogLevel::TRACE, message); } +void CLogger::debug(const std::string & message) const { log(ELogLevel::DEBUG, message); } +void CLogger::info(const std::string & message) const { log(ELogLevel::INFO, message); } +void CLogger::warn(const std::string & message) const { log(ELogLevel::WARN, message); } +void CLogger::error(const std::string & message) const { log(ELogLevel::ERROR, message); } -CLoggerStream CLogger::traceStream() const -{ - return CLoggerStream(*this, ELogLevel::TRACE); -} - -void CLogger::debug(const std::string & message) const -{ - log(ELogLevel::DEBUG, message); -} - -CLoggerStream CLogger::debugStream() const -{ - return CLoggerStream(*this, ELogLevel::DEBUG); -} - -void CLogger::info(const std::string & message) const -{ - log(ELogLevel::INFO, message); -} - -CLoggerStream CLogger::infoStream() const -{ - return CLoggerStream(*this, ELogLevel::INFO); -} - -void CLogger::warn(const std::string & message) const -{ - log(ELogLevel::WARN, message); -} - -CLoggerStream CLogger::warnStream() const -{ - return CLoggerStream(*this, ELogLevel::WARN); -} - -void CLogger::error(const std::string & message) const -{ - log(ELogLevel::ERROR, message); -} - -CLoggerStream CLogger::errorStream() const -{ - return CLoggerStream(*this, ELogLevel::ERROR); -} +CLoggerStream CLogger::traceStream() const { return CLoggerStream(*this, ELogLevel::TRACE); } +CLoggerStream CLogger::debugStream() const { return CLoggerStream(*this, ELogLevel::DEBUG); } +CLoggerStream CLogger::infoStream() const { return CLoggerStream(*this, ELogLevel::INFO); } +CLoggerStream CLogger::warnStream() const { return CLoggerStream(*this, ELogLevel::WARN); } +CLoggerStream CLogger::errorStream() const { return CLoggerStream(*this, ELogLevel::ERROR); } void CLogger::log(ELogLevel::ELogLevel level, const std::string & message) const { if(getEffectiveLevel() <= level) - { callTargets(LogRecord(domain, level, message)); - } } ELogLevel::ELogLevel CLogger::getLevel() const @@ -169,14 +128,11 @@ ELogLevel::ELogLevel CLogger::getLevel() const void CLogger::setLevel(ELogLevel::ELogLevel level) { TLockGuard _(mx); - if(domain.isGlobalDomain() && level == ELogLevel::NOT_SET) return; - this->level = level; + if (!domain.isGlobalDomain() || level != ELogLevel::NOT_SET) + this->level = level; } -const CLoggerDomain & CLogger::getDomain() const -{ - return domain; -} +const CLoggerDomain & CLogger::getDomain() const { return domain; } void CLogger::addTarget(unique_ptr && target) { @@ -187,9 +143,8 @@ void CLogger::addTarget(unique_ptr && target) ELogLevel::ELogLevel CLogger::getEffectiveLevel() const { for(const CLogger * logger = this; logger != nullptr; logger = logger->parent) - { - if(logger->getLevel() != ELogLevel::NOT_SET) return logger->getLevel(); - } + if(logger->getLevel() != ELogLevel::NOT_SET) + return logger->getLevel(); // This shouldn't be reached, as the root logger must have set a log level return ELogLevel::INFO; @@ -199,12 +154,8 @@ void CLogger::callTargets(const LogRecord & record) const { TLockGuard _(mx); for(const CLogger * logger = this; logger != nullptr; logger = logger->parent) - { for(auto & target : logger->targets) - { target->write(record); - } - } } void CLogger::clearTargets() @@ -213,26 +164,15 @@ void CLogger::clearTargets() targets.clear(); } -bool CLogger::isDebugEnabled() const -{ - return getEffectiveLevel() <= ELogLevel::DEBUG; -} - -bool CLogger::isTraceEnabled() const -{ - return getEffectiveLevel() <= ELogLevel::TRACE; -} +bool CLogger::isDebugEnabled() const { return getEffectiveLevel() <= ELogLevel::DEBUG; } +bool CLogger::isTraceEnabled() const { return getEffectiveLevel() <= ELogLevel::TRACE; } CTraceLogger::CTraceLogger(const CLogger * logger, const std::string & beginMessage, const std::string & endMessage) : logger(logger), endMessage(endMessage) { - logger->traceStream() << beginMessage; -} - -CTraceLogger::~CTraceLogger() -{ - logger->traceStream() << endMessage; + logger->trace(beginMessage); } +CTraceLogger::~CTraceLogger() { logger->trace(std::move(endMessage)); } CLogManager & CLogManager::get() { @@ -241,17 +181,11 @@ CLogManager & CLogManager::get() return instance; } -CLogManager::CLogManager() -{ - -} - +CLogManager::CLogManager() { } CLogManager::~CLogManager() { for(auto & i : loggers) - { delete i.second; - } } void CLogManager::addLogger(CLogger * logger) @@ -265,34 +199,30 @@ CLogger * CLogManager::getLogger(const CLoggerDomain & domain) TLockGuard _(mx); auto it = loggers.find(domain.getName()); if(it != loggers.end()) - { return it->second; - } else - { return nullptr; - } } -CLogFormatter::CLogFormatter() : pattern("%m") +CLogFormatter::CLogFormatter() : CLogFormatter("%m") { } + +CLogFormatter::CLogFormatter(const std::string & pattern) : pattern(pattern) { boost::posix_time::time_facet * facet = new boost::posix_time::time_facet("%H:%M:%S"); dateStream.imbue(std::locale(dateStream.getloc(), facet)); } -CLogFormatter::CLogFormatter(const std::string & pattern) -{ - setPattern(pattern); -} +CLogFormatter::CLogFormatter(const CLogFormatter & c) : pattern(c.pattern) { } +CLogFormatter::CLogFormatter(CLogFormatter && m) : pattern(std::move(m.pattern)) { } -CLogFormatter::CLogFormatter(const CLogFormatter & other) +CLogFormatter & CLogFormatter::operator=(const CLogFormatter & c) { - *this = other; + pattern = c.pattern; + return *this; } - -CLogFormatter & CLogFormatter::operator=(const CLogFormatter & other) +CLogFormatter & CLogFormatter::operator=(CLogFormatter && m) { - pattern = other.pattern; + pattern = std::move(m.pattern); return *this; } @@ -336,15 +266,10 @@ std::string CLogFormatter::format(const LogRecord & record) const return message; } -void CLogFormatter::setPattern(const std::string & pattern) -{ - this->pattern = pattern; -} +void CLogFormatter::setPattern(const std::string & pattern) { this->pattern = pattern; } +void CLogFormatter::setPattern(std::string && pattern) { this->pattern = std::move(pattern); } -const std::string & CLogFormatter::getPattern() const -{ - return pattern; -} +const std::string & CLogFormatter::getPattern() const { return pattern; } CColorMapping::CColorMapping() { @@ -365,30 +290,24 @@ void CColorMapping::setColorFor(const CLoggerDomain & domain, ELogLevel::ELogLev EConsoleTextColor::EConsoleTextColor CColorMapping::getColorFor(const CLoggerDomain & domain, ELogLevel::ELogLevel level) const { - std::string name = domain.getName(); + CLoggerDomain currentDomain = domain; while(true) { - const auto & loggerPair = map.find(name); + const auto & loggerPair = map.find(currentDomain.getName()); if(loggerPair != map.end()) { const auto & levelMap = loggerPair->second; const auto & levelPair = levelMap.find(level); if(levelPair != levelMap.end()) - { return levelPair->second; - } } - CLoggerDomain currentDomain(name); - if(!currentDomain.isGlobalDomain()) - { - name = currentDomain.getParent().getName(); - } - else - { + if (currentDomain.isGlobalDomain()) break; - } + + currentDomain = currentDomain.getParent(); } + throw std::runtime_error("failed to find color for requested domain/level pair"); } @@ -399,103 +318,56 @@ CLogConsoleTarget::CLogConsoleTarget(CConsoleHandler * console) : console(consol void CLogConsoleTarget::write(const LogRecord & record) { - if(threshold > record.level) return; + if(threshold > record.level) + return; std::string message = formatter.format(record); -#ifdef __ANDROID__ - __android_log_print(ANDROID_LOG_INFO, "VCMI", "%s", message.c_str()); +#ifdef VCMI_ANDROID + __android_log_write(ELogLevel::toAndroid(record.level), "VCMI", message.c_str()); #endif - bool printToStdErr = record.level >= ELogLevel::WARN; + const bool printToStdErr = record.level >= ELogLevel::WARN; if(console) { - if(coloredOutputEnabled) - { - console->print(message, true, colorMapping.getColorFor(record.domain, record.level)); - } - else - { - console->print(message, true, EConsoleTextColor::DEFAULT, printToStdErr); - } + const EConsoleTextColor::EConsoleTextColor textColor = + coloredOutputEnabled ? colorMapping.getColorFor(record.domain, record.level) : EConsoleTextColor::DEFAULT; + + console->print(message, true, textColor, printToStdErr); } else { TLockGuard _(mx); if(printToStdErr) - { std::cerr << message << std::endl; - } else - { std::cout << message << std::endl; - } } } -bool CLogConsoleTarget::isColoredOutputEnabled() const -{ - return coloredOutputEnabled; -} +bool CLogConsoleTarget::isColoredOutputEnabled() const { return coloredOutputEnabled; } +void CLogConsoleTarget::setColoredOutputEnabled(bool coloredOutputEnabled) { this->coloredOutputEnabled = coloredOutputEnabled; } -void CLogConsoleTarget::setColoredOutputEnabled(bool coloredOutputEnabled) -{ - this->coloredOutputEnabled = coloredOutputEnabled; -} +ELogLevel::ELogLevel CLogConsoleTarget::getThreshold() const { return threshold; } +void CLogConsoleTarget::setThreshold(ELogLevel::ELogLevel threshold) { this->threshold = threshold; } -ELogLevel::ELogLevel CLogConsoleTarget::getThreshold() const -{ - return threshold; -} +const CLogFormatter & CLogConsoleTarget::getFormatter() const { return formatter; } +void CLogConsoleTarget::setFormatter(const CLogFormatter & formatter) { this->formatter = formatter; } -void CLogConsoleTarget::setThreshold(ELogLevel::ELogLevel threshold) -{ - this->threshold = threshold; -} +const CColorMapping & CLogConsoleTarget::getColorMapping() const { return colorMapping; } +void CLogConsoleTarget::setColorMapping(const CColorMapping & colorMapping) { this->colorMapping = colorMapping; } -const CLogFormatter & CLogConsoleTarget::getFormatter() const -{ - return formatter; -} - -void CLogConsoleTarget::setFormatter(const CLogFormatter & formatter) -{ - this->formatter = formatter; -} - -const CColorMapping & CLogConsoleTarget::getColorMapping() const -{ - return colorMapping; -} - -void CLogConsoleTarget::setColorMapping(const CColorMapping & colorMapping) -{ - this->colorMapping = colorMapping; -} - -CLogFileTarget::CLogFileTarget(const std::string & filePath, bool append /*= true*/) - : file(filePath, append ? std::ios_base::app : std::ios_base::out) +CLogFileTarget::CLogFileTarget(boost::filesystem::path filePath, bool append /*= true*/) + : file(std::move(filePath), append ? std::ios_base::app : std::ios_base::out) { formatter.setPattern("%d %l %n [%t] - %m"); } -CLogFileTarget::~CLogFileTarget() -{ - file.close(); -} - void CLogFileTarget::write(const LogRecord & record) { TLockGuard _(mx); file << formatter.format(record) << std::endl; } -const CLogFormatter & CLogFileTarget::getFormatter() const -{ - return formatter; -} - -void CLogFileTarget::setFormatter(const CLogFormatter & formatter) -{ - this->formatter = formatter; -} +const CLogFormatter & CLogFileTarget::getFormatter() const { return formatter; } +void CLogFileTarget::setFormatter(const CLogFormatter & formatter) { this->formatter = formatter; } \ No newline at end of file diff --git a/lib/logging/CLogger.h b/lib/logging/CLogger.h index 9e5afe2db..c6a5737f0 100644 --- a/lib/logging/CLogger.h +++ b/lib/logging/CLogger.h @@ -19,15 +19,19 @@ class ILogTarget; namespace ELogLevel { -enum ELogLevel -{ - NOT_SET = 0, - TRACE, - DEBUG, - INFO, - WARN, - ERROR -}; + enum ELogLevel + { + NOT_SET = 0, + TRACE, + DEBUG, + INFO, + WARN, + ERROR + }; + + #ifdef VCMI_ANDROID + int toAndroid(ELogLevel logLevel); + #endif } /// The class CLoggerDomain provides convenient access to super domains from a sub domain. @@ -36,9 +40,9 @@ class DLL_LINKAGE CLoggerDomain public: /// Constructs a CLoggerDomain with the domain designated by name. /// Sub-domains can be specified by separating domains by a dot, e.g. "ai.battle". The global domain is named "global". - explicit CLoggerDomain(const std::string & name); + explicit CLoggerDomain(std::string name); - std::string getName() const; + const std::string& getName() const; CLoggerDomain getParent() const; bool isGlobalDomain() const; @@ -58,8 +62,11 @@ public: template CLoggerStream & operator<<(const T & data) { - if(!sbuffer) sbuffer = new std::stringstream(); + if(!sbuffer) + sbuffer = new std::stringstream(std::ios_base::out); + (*sbuffer) << data; + return *this; } @@ -84,18 +91,16 @@ public: /// Log methods for various log levels void trace(const std::string & message) const; - CLoggerStream traceStream() const; - void debug(const std::string & message) const; - CLoggerStream debugStream() const; - void info(const std::string & message) const; - CLoggerStream infoStream() const; - void warn(const std::string & message) const; - CLoggerStream warnStream() const; - void error(const std::string & message) const; + + /// Log streams for various log levels + CLoggerStream traceStream() const; + CLoggerStream debugStream() const; + CLoggerStream infoStream() const; + CLoggerStream warnStream() const; CLoggerStream errorStream() const; inline void log(ELogLevel::ELogLevel level, const std::string & message) const; @@ -184,10 +189,7 @@ struct DLL_LINKAGE LogRecord { LogRecord(const CLoggerDomain & domain, ELogLevel::ELogLevel level, const std::string & message) : domain(domain), level(level), message(message), timeStamp(boost::posix_time::second_clock::local_time()), - threadId(boost::this_thread::get_id()) - { - - } + threadId(boost::this_thread::get_id()) { } CLoggerDomain domain; ELogLevel::ELogLevel level; @@ -208,12 +210,17 @@ class DLL_LINKAGE CLogFormatter { public: CLogFormatter(); - CLogFormatter(const std::string & pattern); + CLogFormatter(const CLogFormatter & copy); + CLogFormatter(CLogFormatter && move); - CLogFormatter(const CLogFormatter & other); - CLogFormatter & operator=(const CLogFormatter & other); + CLogFormatter(const std::string & pattern); + + CLogFormatter & operator=(const CLogFormatter & copy); + CLogFormatter & operator=(CLogFormatter && move); void setPattern(const std::string & pattern); + void setPattern(std::string && pattern); + const std::string & getPattern() const; std::string format(const LogRecord & record) const; @@ -284,8 +291,7 @@ class DLL_LINKAGE CLogFileTarget : public ILogTarget public: /// Constructs a CLogFileTarget and opens the file designated by filePath. If the append parameter is true, the file /// will be appended to. Otherwise the file designated by filePath will be truncated before being opened. - explicit CLogFileTarget(const std::string & filePath, bool append = true); - ~CLogFileTarget(); + explicit CLogFileTarget(boost::filesystem::path filePath, bool append = true); const CLogFormatter & getFormatter() const; void setFormatter(const CLogFormatter & formatter); @@ -293,7 +299,7 @@ public: void write(const LogRecord & record) override; private: - std::ofstream file; + boost::filesystem::ofstream file; CLogFormatter formatter; mutable boost::mutex mx; }; diff --git a/lib/mapObjects/CArmedInstance.h b/lib/mapObjects/CArmedInstance.h index 9b58332ca..0ebe2abc1 100644 --- a/lib/mapObjects/CArmedInstance.h +++ b/lib/mapObjects/CArmedInstance.h @@ -13,7 +13,7 @@ * */ -class BattleInfo; +struct BattleInfo; class CGameState; class DLL_LINKAGE CArmedInstance: public CGObjectInstance, public CBonusSystemNode, public CCreatureSet diff --git a/lib/mapObjects/CBank.h b/lib/mapObjects/CBank.h index cfecdf20c..59b954116 100644 --- a/lib/mapObjects/CBank.h +++ b/lib/mapObjects/CBank.h @@ -13,7 +13,7 @@ * */ -class BankConfig; +struct BankConfig; class CBankInstanceConstructor; class DLL_LINKAGE CBank : public CArmedInstance diff --git a/lib/mapObjects/CGHeroInstance.h b/lib/mapObjects/CGHeroInstance.h index 9f811c4b2..69c65cd06 100644 --- a/lib/mapObjects/CGHeroInstance.h +++ b/lib/mapObjects/CGHeroInstance.h @@ -19,7 +19,7 @@ class CHero; class CGBoat; class CGTownInstance; -class TerrainTile; +struct TerrainTile; class CGHeroPlaceholder : public CGObjectInstance { diff --git a/lib/mapObjects/CGPandoraBox.h b/lib/mapObjects/CGPandoraBox.h index c2ad87dde..974351b83 100644 --- a/lib/mapObjects/CGPandoraBox.h +++ b/lib/mapObjects/CGPandoraBox.h @@ -14,7 +14,7 @@ * */ -class InfoWindow; +struct InfoWindow; class DLL_LINKAGE CGPandoraBox : public CArmedInstance { diff --git a/lib/mapObjects/CObjectHandler.h b/lib/mapObjects/CObjectHandler.h index 0b27d759e..adc71b3d1 100644 --- a/lib/mapObjects/CObjectHandler.h +++ b/lib/mapObjects/CObjectHandler.h @@ -19,7 +19,7 @@ class CGHeroInstance; class IGameCallback; class CGObjectInstance; -class MetaString; +struct MetaString; struct BattleResult; class DLL_LINKAGE IObjectInterface diff --git a/lib/rmg/float3.h b/lib/rmg/float3.h index 36f6feba0..402ba66b0 100644 --- a/lib/rmg/float3.h +++ b/lib/rmg/float3.h @@ -10,75 +10,103 @@ * */ +// FIXME: Class doesn't contain three float values. Update name and description. /// Class which consists of three float values. Represents position virtual RMG (0;1) area. class float3 { public: float x, y; si32 z; - inline float3():x(0),y(0),z(0){}; //c-tor, x/y/z initialized to 0 - inline float3(const float X, const float Y, const si32 Z):x(X),y(Y),z(Z){}; //c-tor - inline float3(const float3 & val) : x(val.x), y(val.y), z(val.z){} //copy c-tor - inline float3 & operator=(const float3 & val) {x = val.x; y = val.y; z = val.z; return *this;} //assignemt operator - ~float3() {} // d-tor - does nothing - inline float3 operator+(const float3 & i) const //returns float3 with coordinates increased by corresponding coordinate of given float3 - {return float3(x+i.x,y+i.y,z+i.z);} - inline float3 operator+(const float i) const //returns float3 with coordinates increased by given numer - {return float3(x+i,y+i,z+i);} - inline float3 operator-(const float3 & i) const //returns float3 with coordinates decreased by corresponding coordinate of given float3 - {return float3(x-i.x,y-i.y,z-i.z);} - inline float3 operator-(const float i) const //returns float3 with coordinates decreased by given numer - {return float3(x-i,y-i,z-i);} - inline float3 operator*(const float i) const //returns float3 with plane coordinates decreased by given numer - {return float3(x*i, y*i, z);} - inline float3 operator/(const float i) const //returns float3 with plane coordinates decreased by given numer - {return float3(x/i, y/i, z);} - inline float3 operator-() const //returns opposite position - {return float3(-x,-y,-z);} - inline double dist2d(const float3 &other) const //distance (z coord is not used) - {return std::sqrt((double)(x-other.x)*(x-other.x) + (y-other.y)*(y-other.y));} - inline bool areNeighbours(const float3 &other) const - {return dist2d(other) < 2. && z == other.z;} - inline void operator+=(const float3 & i) + + float3() : x(0), y(0), z(0) {} + float3(const float X, const float Y, const si32 Z): x(X), y(Y), z(Z) {} + float3(const float3 & copy) : x(copy.x), y(copy.y), z(copy.z) {} + float3 & operator=(const float3 & copy) { x = copy.x; y = copy.y; z = copy.z; return *this; } + + // returns float3 with coordinates increased by corresponding coordinate of given float3 + float3 operator+(const float3 & i) const { return float3(x + i.x, y + i.y, z + i.z); } + // returns float3 with coordinates increased by given numer + float3 operator+(const float i) const { return float3(x + i, y + i, z + (si32)i); } + // returns float3 with coordinates decreased by corresponding coordinate of given float3 + float3 operator-(const float3 & i) const { return float3(x - i.x, y - i.y, z - i.z); } + // returns float3 with coordinates decreased by given numer + float3 operator-(const float i) const { return float3(x - i, y - i, z - (si32)i); } + + // returns float3 with plane coordinates decreased by given numer + float3 operator*(const float i) const {return float3(x * i, y * i, z);} + // returns float3 with plane coordinates decreased by given numer + float3 operator/(const float i) const {return float3(x / i, y / i, z);} + + // returns opposite position + float3 operator-() const { return float3(-x, -y, -z); } + + // returns squared distance on Oxy plane (z coord is not used) + double dist2dSQ(const float3 & o) const { - x+=i.x; - y+=i.y; - z+=i.z; + const double dx = (x - o.x); + const double dy = (y - o.y); + return dx*dx + dy*dy; } - inline void operator+=(const float & i) + // returns distance on Oxy plane (z coord is not used) + double dist2d(const float3 &other) const { return std::sqrt(dist2dSQ(other)); } + + bool areNeighbours(const float3 &other) const { return (dist2dSQ(other) < 4.0) && z == other.z; } + + float3& operator+=(const float3 & i) { - x+=i; - y+=i; - z+=i; + x += i.x; + y += i.y; + z += i.z; + + return *this; } - inline void operator-=(const float3 & i) + float3& operator+=(const float & i) { - x-=i.x; - y-=i.y; - z-=i.z; + x += i; + y += i; + z += (si32)i; + + return *this; } - inline void operator-=(const float & i) + + float3& operator-=(const float3 & i) { - x+=i; - y+=i; - z+=i; + x -= i.x; + y -= i.y; + z -= i.z; + + return *this; } - inline void operator*=(const float & i) //scale on plane + float3& operator-=(const float & i) { - x*=i; - y*=i; - } - inline void operator/=(const float & i) //scale on plane - { - x/=i; - y/=i; + x += i; + y += i; + z += (si32)i; + + return *this; } - inline bool operator==(const float3 & i) const - {return (x==i.x) && (y==i.y) && (z==i.z);} - inline bool operator!=(const float3 & i) const - {return !(*this==i);} - inline bool operator<(const float3 & i) const + // scale on plane + float3& operator*=(const float & i) + { + x *= i; + y *= i; + + return *this; + } + // scale on plane + float3& operator/=(const float & i) + { + x /= i; + y /= i; + + return *this; + } + + bool operator==(const float3 & i) const { return (x == i.x) && (y == i.y) && (z == i.z); } + bool operator!=(const float3 & i) const { return (x != i.x) || (y != i.y) || (z != i.z); } + + bool operator<(const float3 & i) const { if (zi.x) return false; + return false; } - inline std::string operator ()() const + + std::string operator ()() const { return "(" + boost::lexical_cast(x) + " " + boost::lexical_cast(y) + " " + boost::lexical_cast(z) + ")"; } - inline bool valid() const + + bool valid() const { return z >= 0; //minimal condition that needs to be fulfilled for tiles in the map } + template void serialize(Handler &h, const float version) { h & x & y & z; } - }; + inline std::istream & operator>>(std::istream & str, float3 & dest) { - str>>dest.x>>dest.y>>dest.z; - return str; + return str >> dest.x >> dest.y >> dest.z; } inline std::ostream & operator<<(std::ostream & str, const float3 & sth) { - return str<warnStream() << "Warning: Folder " << VCMIDirs::get().dataPaths().back() << "/Data/s/ doesn't exist!"; + logGlobal->warnStream() << "Warning: Folder " << dataPath << " doesn't exist!"; return; } directory_iterator enddir; - for (directory_iterator dir(VCMIDirs::get().dataPaths().back() + "/Data/s"); dir!=enddir; dir++) + for (directory_iterator dir(dataPath); dir!=enddir; dir++) { if(is_regular(dir->status())) { - std::string name = dir->path().leaf().string(); - if( boost::algorithm::ends_with(name, ".erm") || - boost::algorithm::ends_with(name, ".verm") ) + const std::string ext = boost::to_upper_copy(dir->path().extension().string()); + if (ext == ".ERM" || ext == ".VERM") { ERMParser ep(dir->path().string()); FileInfo * finfo = new FileInfo; diff --git a/server/CVCMIServer.cpp b/server/CVCMIServer.cpp index 2d5ca8533..4a572459c 100644 --- a/server/CVCMIServer.cpp +++ b/server/CVCMIServer.cpp @@ -18,7 +18,7 @@ #include "CVCMIServer.h" #include "../lib/StartInfo.h" #include "../lib/mapping/CMap.h" -#ifndef __ANDROID__ +#ifndef VCMI_ANDROID #include "../lib/Interprocess.h" #endif #include "../lib/VCMI_Lib.h" @@ -32,7 +32,7 @@ #include "../lib/UnlockGuard.h" -#if defined(__GNUC__) && !defined (__MINGW32__) && !defined(__ANDROID__) +#if defined(__GNUC__) && !defined (__MINGW32__) && !defined(VCMI_ANDROID) #include #endif @@ -41,7 +41,7 @@ std::string NAME = GameConstants::VCMI_VERSION + std::string(" (") + NAME_AFFIX using namespace boost; using namespace boost::asio; using namespace boost::asio::ip; -#ifndef __ANDROID__ +#ifndef VCMI_ANDROID namespace intpr = boost::interprocess; #endif bool end2 = false; @@ -393,7 +393,7 @@ void CVCMIServer::newPregame() void CVCMIServer::start() { -#ifndef __ANDROID__ +#ifndef VCMI_ANDROID ServerReady *sr = nullptr; intpr::mapped_region *mr; try @@ -416,7 +416,7 @@ void CVCMIServer::start() logNetwork->infoStream()<<"Listening for connections at port " << acceptor->local_endpoint().port(); auto s = new tcp::socket(acceptor->get_io_service()); boost::thread acc(std::bind(vaccept,acceptor,s,&error)); -#ifndef __ANDROID__ +#ifndef VCMI_ANDROID sr->setToTrueAndNotify(); delete mr; #endif @@ -560,7 +560,7 @@ static void handleCommandOptions(int argc, char *argv[]) } } -#if defined(__GNUC__) && !defined (__MINGW32__) && !defined(__ANDROID__) +#if defined(__GNUC__) && !defined (__MINGW32__) && !defined(VCMI_ANDROID) void handleLinuxSignal(int sig) { const int STACKTRACE_SIZE = 100; @@ -591,12 +591,12 @@ int main(int argc, char** argv) { // Installs a sig sev segmentation violation handler // to log stacktrace - #if defined(__GNUC__) && !defined (__MINGW32__) && !defined(__ANDROID__) + #if defined(__GNUC__) && !defined (__MINGW32__) && !defined(VCMI_ANDROID) signal(SIGSEGV, handleLinuxSignal); #endif console = new CConsoleHandler; - CBasicLogConfigurator logConfig(VCMIDirs::get().userCachePath() + "/VCMI_Server_log.txt", console); + CBasicLogConfigurator logConfig(VCMIDirs::get().userCachePath() / "VCMI_Server_log.txt", console); logConfig.configureDefault(); preinitDLL(console); diff --git a/test/CVcmiTestConfig.cpp b/test/CVcmiTestConfig.cpp index a56c7f380..cbe0deced 100644 --- a/test/CVcmiTestConfig.cpp +++ b/test/CVcmiTestConfig.cpp @@ -22,7 +22,7 @@ CVcmiTestConfig::CVcmiTestConfig() { console = new CConsoleHandler; - CBasicLogConfigurator logConfig(VCMIDirs::get().userCachePath() + "/VCMI_Test_log.txt", console); + CBasicLogConfigurator logConfig(VCMIDirs::get().userCachePath() / "VCMI_Test_log.txt", console); logConfig.configureDefault(); preinitDLL(console); settings.init();