mirror of
https://github.com/vcmi/vcmi.git
synced 2025-01-26 03:52:01 +02:00
Merge branch 'develop' of github.com:karol57/vcmi into karol57-develop
This commit is contained in:
commit
de9c5b1af7
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
||||
|
80
Global.h
80
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 <Windows.h>. Use std::[min/max] from <algorithm> instead.
|
||||
#endif
|
||||
|
||||
#define _USE_MATH_DEFINES
|
||||
|
||||
#include <cstdio>
|
||||
@ -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 <boost/date_time/posix_time/posix_time.hpp>
|
||||
#include <boost/date_time/posix_time/posix_time_io.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
#include <boost/format.hpp>
|
||||
#include <boost/functional/hash.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/locale/generator.hpp>
|
||||
#include <boost/logic/tribool.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
#include <boost/program_options.hpp>
|
||||
@ -112,13 +163,8 @@ static_assert(sizeof(bool) == 1, "Bool needs to be 1 byte in size.");
|
||||
#include <boost/variant.hpp>
|
||||
#include <boost/math/special_functions/round.hpp>
|
||||
|
||||
|
||||
#ifdef ANDROID
|
||||
#include <android/log.h>
|
||||
#endif
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
# define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
/* ---------------------------------------------------------------------------- */
|
||||
@ -151,30 +197,20 @@ typedef boost::lock_guard<boost::recursive_mutex> 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
|
||||
|
@ -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<bool> 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<SDL_Event> 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 <getopt.h>
|
||||
#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<std::string>(), "runs game in duel mode (battle-only")
|
||||
("start", po::value<std::string>(), "starts game from saved StartInfo file")
|
||||
("start", po::value<bfs::path>(), "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<std::vector<std::string>>(), "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: "<<pomtime.getDiff();
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
#if defined(VCMI_ANDROID)
|
||||
//on Android threaded init is broken
|
||||
#define VCMI_NO_THREADED_LOAD
|
||||
#endif // defined
|
||||
@ -430,15 +428,15 @@ int main(int argc, char** argv)
|
||||
session["autoSkip"].Bool() = vm.count("autoSkip");
|
||||
session["oneGoodAI"].Bool() = vm.count("oneGoodAI");
|
||||
|
||||
std::string fileToStartFrom; //none by default
|
||||
bfs::path fileToStartFrom; //none by default
|
||||
if(vm.count("start"))
|
||||
fileToStartFrom = vm["start"].as<std::string>();
|
||||
fileToStartFrom = vm["start"].as<bfs::path>();
|
||||
|
||||
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; i<cde->ourImages.size(); i++)
|
||||
for (size_t i = 0; i < cde->ourImages.size(); ++i)
|
||||
{
|
||||
std::string filename = outPath + outName + '/' + boost::lexical_cast<std::string>(i) + ".bmp";
|
||||
SDL_SaveBMP(cde->ourImages[i].bitmap, filename.c_str());
|
||||
const bfs::path filePath = outPath / (boost::lexical_cast<std::string>(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);
|
||||
|
@ -42,13 +42,6 @@
|
||||
#include "../lib/UnlockGuard.h"
|
||||
#include <SDL.h>
|
||||
|
||||
#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<std::time_t, int> 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<int>(nr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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 <windows.h>
|
||||
|
||||
#pragma pack(push,1)
|
||||
|
@ -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<intpr::interprocess_mutex> 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<std::string>(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";
|
||||
|
@ -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);
|
||||
|
@ -8,4 +8,13 @@
|
||||
#include <QVector>
|
||||
#include <QList>
|
||||
#include <QString>
|
||||
#include <QFile>
|
||||
#include <QFile>
|
||||
|
||||
inline QString pathToQString(const boost::filesystem::path & path)
|
||||
{
|
||||
#ifdef VCMI_WINDOWS
|
||||
return QString::fromStdWString(path.wstring());
|
||||
#else
|
||||
return QString::fromStdString(path.string());
|
||||
#endif
|
||||
}
|
@ -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");
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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()
|
||||
|
@ -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;
|
||||
|
@ -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> BattleHex::neighbouringTiles() const
|
||||
{
|
||||
std::vector<BattleHex> 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<BattleHex> & ret)
|
||||
|
@ -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<typename inttype>
|
||||
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<si16, si16> getXY() const
|
||||
{
|
||||
return std::make_pair(getX(), getY());
|
||||
}
|
||||
std::pair<si16, si16> 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<BattleHex> neighbouringTiles() const;
|
||||
|
||||
|
@ -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 <Windows.h>
|
||||
#ifndef __MINGW32__
|
||||
#include <dbghelp.h>
|
||||
@ -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);
|
||||
|
@ -38,7 +38,7 @@ public:
|
||||
template<typename T> 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
|
||||
}
|
||||
|
@ -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 <windows.h> //for .dll libs
|
||||
#else
|
||||
#include <dlfcn.h>
|
||||
@ -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<CGlobalAI> &out);
|
||||
@ -35,7 +34,7 @@ extern "C" DLL_EXPORT void BattleAI_GetNewBattleAI(shared_ptr<CBattleGameInterfa
|
||||
#endif
|
||||
|
||||
template<typename rett>
|
||||
shared_ptr<rett> createAny(std::string dllname, std::string methodName)
|
||||
shared_ptr<rett> createAny(const boost::filesystem::path& libpath, const std::string& methodName)
|
||||
{
|
||||
typedef void(*TGetAIFun)(shared_ptr<rett>&);
|
||||
typedef void(*TGetNameFun)(char*);
|
||||
@ -45,56 +44,60 @@ shared_ptr<rett> 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 ("<<dllname<<"). Throwing...";
|
||||
logGlobal->errorStream() << "Cannot open dynamic library ("<<libpath<<"). Throwing...";
|
||||
throw std::runtime_error("Cannot open dynamic library");
|
||||
}
|
||||
else if(!getName || !getAI)
|
||||
{
|
||||
logGlobal->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<rett> createAny(std::string dllname, std::string methodName)
|
||||
}
|
||||
|
||||
template<typename rett>
|
||||
shared_ptr<rett> createAnyAI(std::string dllname, std::string methodName)
|
||||
shared_ptr<rett> createAnyAI(std::string dllname, const std::string& methodName)
|
||||
{
|
||||
logGlobal->infoStream() << "Opening " << dllname;
|
||||
std::string filename = VCMIDirs::get().libraryName(dllname);
|
||||
|
||||
auto ret = createAny<rett>(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<rett>(filePath, methodName);
|
||||
ret->dllName = std::move(dllname);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
#include "StdInc.h"
|
||||
#include "CThreadHelper.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifdef VCMI_WINDOWS
|
||||
#include <windows.h>
|
||||
#elif !defined(__APPLE__)
|
||||
#elif !defined(VCMI_APPLE)
|
||||
#include <sys/prctl.h>
|
||||
#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;
|
||||
|
32
lib/CondSh.h
32
lib/CondSh.h
@ -17,50 +17,48 @@ template <typename T> 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<boost::mutex> 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<boost::mutex> lock(mx);
|
||||
data=t;
|
||||
}
|
||||
set(t);
|
||||
cond.notify_all();
|
||||
};
|
||||
|
||||
T get() //get stored value
|
||||
// get stored value
|
||||
T get()
|
||||
{
|
||||
boost::unique_lock<boost::mutex> 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<boost::mutex> 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<boost::mutex> 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<boost::mutex> un(mx);
|
||||
while(data != t)
|
||||
|
@ -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<std::ifstream>(fname, std::ios::binary);
|
||||
fName = fname.string();
|
||||
sfile = make_unique<boost::filesystem::ifstream>(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(...)
|
||||
|
@ -1530,17 +1530,17 @@ class DLL_LINKAGE CLoadFile
|
||||
|
||||
public:
|
||||
std::string fName;
|
||||
unique_ptr<std::ifstream> sfile;
|
||||
unique_ptr<boost::filesystem::ifstream> 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<CLoadIntegrityValidator>
|
||||
|
679
lib/VCMIDirs.cpp
679
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 <Windows.h>
|
||||
#include <Shlobj.h>
|
||||
#include <Shellapi.h>
|
||||
|
||||
// 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<boost::filesystem::path> 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<wchar_t[]>
|
||||
{
|
||||
const std::wstring& pathStr = path.native();
|
||||
std::unique_ptr<wchar_t[]> 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<bfs::path> VCMIDirsWIN32::dataPaths() const
|
||||
{
|
||||
return std::vector<bfs::path>(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<std::string> 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<std::string> 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<std::string>(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<std::string> 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<boost::filesystem::path> 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<bfs::path> VCMIDirsOSX::dataPaths() const
|
||||
{
|
||||
return std::vector<bfs::path>(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<boost::filesystem::path> 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<bfs::path> VCMIDirsLinux::dataPaths() const
|
||||
{
|
||||
return "./vcmiclient";
|
||||
}
|
||||
// $XDG_DATA_DIRS, default: /usr/local/share/:/usr/share/
|
||||
|
||||
std::string VCMIDirs::serverPath() const
|
||||
{
|
||||
return "./vcmiserver";
|
||||
}
|
||||
|
||||
std::vector<std::string> VCMIDirs::dataPaths() const
|
||||
{
|
||||
return std::vector<std::string>(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<std::string> VCMIDirs::dataPaths() const
|
||||
{
|
||||
// construct list in reverse.
|
||||
// in specification first directory has highest priority
|
||||
// in vcmi fs last directory has highest priority
|
||||
std::vector<bfs::path> ret;
|
||||
|
||||
std::vector<std::string> 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<std::string> dataDirs;
|
||||
boost::split(dataDirs, dataDirsEnv, boost::is_any_of(":"));
|
||||
for (auto & entry : boost::adaptors::reverse(dataDirs))
|
||||
@ -231,21 +516,61 @@ std::vector<std::string> 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<boost::filesystem::path> 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<bfs::path> VCMIDirsAndroid::dataPaths() const
|
||||
{
|
||||
return std::vector<bfs::path>(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;
|
||||
}
|
||||
}
|
@ -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<boost::filesystem::path> 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<std::string> 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();
|
||||
}
|
@ -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 \""<<archive.filename()<<"\" loaded (" << entries.size() << " files found).";
|
||||
}
|
||||
|
||||
void CArchiveLoader::initLODArchive(const std::string &mountPoint, CFileInputStream & fileStream)
|
||||
@ -61,7 +52,7 @@ void CArchiveLoader::initLODArchive(const std::string &mountPoint, CFileInputStr
|
||||
fileStream.seek(0x5c);
|
||||
|
||||
// Insert entries to list
|
||||
for(ui32 i = 0; i < totalFiles; i++)
|
||||
for(ui32 i = 0; i < totalFiles; ++i)
|
||||
{
|
||||
char filename[16];
|
||||
reader.read(reinterpret_cast<ui8*>(filename), 16);
|
||||
@ -90,7 +81,7 @@ void CArchiveLoader::initVIDArchive(const std::string &mountPoint, CFileInputStr
|
||||
std::set<int> 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<ui8*>(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<ui8*>(filename), 40);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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<CInputStream> CFilesystemLoader::load(const ResourceID & resourc
|
||||
{
|
||||
assert(fileList.count(resourceName));
|
||||
|
||||
std::unique_ptr<CInputStream> stream(new CFileInputStream(baseDirectory + '/' + fileList.at(resourceName)));
|
||||
std::unique_ptr<CInputStream> stream(new CFileInputStream(baseDirectory / fileList.at(resourceName)));
|
||||
return stream;
|
||||
}
|
||||
|
||||
@ -34,7 +36,7 @@ boost::optional<std::string> CFilesystemLoader::getResourceName(const ResourceID
|
||||
{
|
||||
assert(existsResource(resourceName));
|
||||
|
||||
return baseDirectory + '/' + fileList.at(resourceName);
|
||||
return (baseDirectory / fileList.at(resourceName)).string();
|
||||
}
|
||||
|
||||
std::unordered_set<ResourceID> CFilesystemLoader::getFilteredFiles(std::function<bool(const ResourceID &)> filter) const
|
||||
@ -45,7 +47,8 @@ std::unordered_set<ResourceID> 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<ResourceID, std::string> CFilesystemLoader::listFiles(const std::string &mountPoint, size_t depth, bool initial) const
|
||||
std::unordered_map<ResourceID, bfs::path> CFilesystemLoader::listFiles(const std::string &mountPoint, size_t depth, bool initial) const
|
||||
{
|
||||
std::set<EResType::Type> 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<EResType::Type> initialTypes(initArray, initArray + ARRAY_COUNT(initArray));
|
||||
|
||||
assert(boost::filesystem::is_directory(baseDirectory));
|
||||
std::unordered_map<ResourceID, std::string> fileList;
|
||||
assert(bfs::is_directory(baseDirectory));
|
||||
std::unordered_map<ResourceID, bfs::path> fileList;
|
||||
|
||||
std::vector<std::string> path;//vector holding relative path to our file
|
||||
std::vector<bfs::path> 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; i<it.level() && i<path.size(); i++)
|
||||
filename += path[i] + '/';
|
||||
filename += it->path().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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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<std::string> getResourceName(const ResourceID & resourceName) const override;
|
||||
std::unordered_set<ResourceID> getFilteredFiles(std::function<bool(const ResourceID &)> filter) const;
|
||||
std::unordered_set<ResourceID> getFilteredFiles(std::function<bool(const ResourceID &)> 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<ResourceID, std::string> fileList;
|
||||
std::unordered_map<ResourceID, boost::filesystem::path> 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<ResourceID, std::string> listFiles(const std::string &mountPoint, size_t depth, bool initial) const;
|
||||
std::unordered_map<ResourceID, boost::filesystem::path> listFiles(const std::string &mountPoint, size_t depth, bool initial) const;
|
||||
};
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
14
lib/int3.h
14
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 <int3> container and not just any
|
||||
template<typename Container>
|
||||
int3 findClosestTile (Container & container, int3 dest)
|
||||
{
|
||||
int3 result(-1,-1,-1);
|
||||
static_assert(std::is_same<typename Container::value_type, int3>::value,
|
||||
"findClosestTile requires <int3> container.");
|
||||
|
||||
int3 result(-1, -1, -1);
|
||||
ui32 distance = std::numeric_limits<ui32>::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;
|
||||
|
@ -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<std::string, ELogLevel::ELogLevel> 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<std::string, EConsoleTextColor::EConsoleTextColor> 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.");
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -1,46 +1,51 @@
|
||||
#ifdef __ANDROID__
|
||||
#include <android/log.h>
|
||||
#endif
|
||||
|
||||
#include "StdInc.h"
|
||||
#include "CLogger.h"
|
||||
|
||||
#ifdef VCMI_ANDROID
|
||||
#include <android/log.h>
|
||||
|
||||
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<ILogTarget> && target)
|
||||
{
|
||||
@ -187,9 +143,8 @@ void CLogger::addTarget(unique_ptr<ILogTarget> && 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; }
|
@ -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<typename T>
|
||||
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;
|
||||
};
|
||||
|
@ -13,7 +13,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
class BattleInfo;
|
||||
struct BattleInfo;
|
||||
class CGameState;
|
||||
|
||||
class DLL_LINKAGE CArmedInstance: public CGObjectInstance, public CBonusSystemNode, public CCreatureSet
|
||||
|
@ -13,7 +13,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
class BankConfig;
|
||||
struct BankConfig;
|
||||
class CBankInstanceConstructor;
|
||||
|
||||
class DLL_LINKAGE CBank : public CArmedInstance
|
||||
|
@ -19,7 +19,7 @@
|
||||
class CHero;
|
||||
class CGBoat;
|
||||
class CGTownInstance;
|
||||
class TerrainTile;
|
||||
struct TerrainTile;
|
||||
|
||||
class CGHeroPlaceholder : public CGObjectInstance
|
||||
{
|
||||
|
@ -14,7 +14,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
class InfoWindow;
|
||||
struct InfoWindow;
|
||||
|
||||
class DLL_LINKAGE CGPandoraBox : public CArmedInstance
|
||||
{
|
||||
|
@ -19,7 +19,7 @@
|
||||
class CGHeroInstance;
|
||||
class IGameCallback;
|
||||
class CGObjectInstance;
|
||||
class MetaString;
|
||||
struct MetaString;
|
||||
struct BattleResult;
|
||||
|
||||
class DLL_LINKAGE IObjectInterface
|
||||
|
147
lib/rmg/float3.h
147
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 (z<i.z)
|
||||
return true;
|
||||
@ -92,32 +120,35 @@ public:
|
||||
return true;
|
||||
if (x>i.x)
|
||||
return false;
|
||||
|
||||
return false;
|
||||
}
|
||||
inline std::string operator ()() const
|
||||
|
||||
std::string operator ()() const
|
||||
{
|
||||
return "(" + boost::lexical_cast<std::string>(x) +
|
||||
" " + boost::lexical_cast<std::string>(y) +
|
||||
" " + boost::lexical_cast<std::string>(z) + ")";
|
||||
}
|
||||
inline bool valid() const
|
||||
|
||||
bool valid() const
|
||||
{
|
||||
return z >= 0; //minimal condition that needs to be fulfilled for tiles in the map
|
||||
}
|
||||
|
||||
template <typename Handler> 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<<sth.x<<' '<<sth.y<<' '<<sth.z;
|
||||
return str << sth.x << ' ' << sth.y << ' ' << sth.z;
|
||||
}
|
||||
|
||||
struct Shashfloat3
|
||||
|
@ -368,19 +368,19 @@ void ERMInterpreter::scanForScripts()
|
||||
{
|
||||
using namespace boost::filesystem;
|
||||
//parser checking
|
||||
if(!exists(VCMIDirs::get().dataPaths().back() + "/Data/s/"))
|
||||
const path dataPath = VCMIDirs::get().dataPaths().back() / "Data" / "s";
|
||||
if(!exists(dataPath))
|
||||
{
|
||||
logGlobal->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;
|
||||
|
@ -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 <execinfo.h>
|
||||
#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);
|
||||
|
@ -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();
|
||||
|
Loading…
x
Reference in New Issue
Block a user