فهرست منبع

Merge branch 'Zyx-develop' into develop

Conflicts:
	lib/filesystem/AdapterLoaders.h
AlexVinS 9 سال پیش
والد
کامیت
d7c0c3759a

+ 1 - 0
.gitignore

@@ -14,6 +14,7 @@
 *.pro.user
 *.pro.user.*
 *.swp
+*.h.gch
 *~
 /CMakeLists.txt.user
 CMakeCache.txt

+ 1 - 0
AI/BattleAI/BattleAI.cbp

@@ -51,6 +51,7 @@
 			<Add option="-pedantic" />
 			<Add option="-Wextra" />
 			<Add option="-Wall" />
+			<Add option="-std=gnu++11" />
 			<Add option="-fexceptions" />
 			<Add option="-Wpointer-arith" />
 			<Add option="-Wno-switch" />

+ 1 - 0
AI/EmptyAI/EmptyAI.cbp

@@ -49,6 +49,7 @@
 		<Compiler>
 			<Add option="-Wextra" />
 			<Add option="-Wall" />
+			<Add option="-std=gnu++11" />
 			<Add option="-fexceptions" />
 			<Add option="-Wpointer-arith" />
 			<Add option="-Wno-switch" />

+ 1 - 0
AI/FuzzyLite/FuzzyLite.cbp

@@ -52,6 +52,7 @@
 		<Compiler>
 			<Add option="-Wextra" />
 			<Add option="-Wall" />
+			<Add option="-std=gnu++11" />
 			<Add option="-fexceptions" />
 			<Add option="-Wpointer-arith" />
 			<Add option="-Wno-switch" />

+ 1 - 0
AI/StupidAI/StupidAI.cbp

@@ -35,6 +35,7 @@
 			<Add option="-pedantic" />
 			<Add option="-Wextra" />
 			<Add option="-Wall" />
+			<Add option="-std=gnu++11" />
 			<Add option="-fexceptions" />
 			<Add option="-Wpointer-arith" />
 			<Add option="-Wno-switch" />

+ 2 - 1
AI/VCAI/VCAI.cbp

@@ -3,7 +3,7 @@
 	<FileVersion major="1" minor="6" />
 	<Project>
 		<Option title="VCAI" />
-		<Option pch_mode="2" />
+		<Option pch_mode="0" />
 		<Option compiler="gcc" />
 		<Build>
 			<Target title="Debug-win32">
@@ -57,6 +57,7 @@
 			<Add option="-pedantic" />
 			<Add option="-Wextra" />
 			<Add option="-Wall" />
+			<Add option="-std=gnu++11" />
 			<Add option="-fexceptions" />
 			<Add option="-Wpointer-arith" />
 			<Add option="-Wno-switch" />

+ 1 - 0
client/CMT.cpp

@@ -7,6 +7,7 @@
 #include "mapHandler.h"
 
 #include "../lib/filesystem/Filesystem.h"
+#include "../lib/filesystem/FileStream.h"
 #include "CPreGame.h"
 #include "windows/CCastleInterface.h"
 #include "../lib/CConsoleHandler.h"

+ 9 - 9
client/CPreGame.cpp

@@ -307,10 +307,10 @@ void CMenuScreen::switchToTab(size_t index)
 //funciton for std::string -> std::function conversion for main menu
 static std::function<void()> genCommand(CMenuScreen* menu, std::vector<std::string> menuType, const std::string &string)
 {
-	static const std::vector<std::string> commandType  = 
+	static const std::vector<std::string> commandType  =
 		{"to", "campaigns", "start", "load", "exit", "highscores"};
 
-	static const std::vector<std::string> gameType = 
+	static const std::vector<std::string> gameType =
 		{"single", "multi", "campaign", "tutorial"};
 
 	std::list<std::string> commands;
@@ -554,8 +554,8 @@ CGPreGame *CGPreGame::create()
 {
 	if(!CGP)
 		CGP = new CGPreGame();
-		
-	GH.terminate_cond.set(false);		
+
+	GH.terminate_cond.set(false);
 	return CGP;
 }
 
@@ -1151,7 +1151,7 @@ void SelectionTab::parseGames(const std::unordered_set<ResourceID> &files, bool
 			lf >> *(mapInfo.mapHeader.get()) >> mapInfo.scenarioOpts;
 			mapInfo.fileURI = file.getName();
 			mapInfo.countPlayers();
-			std::time_t time = CFileInfo(*CResourceHandler::get()->getResourceName(file)).getDate();
+			std::time_t time = boost::filesystem::last_write_time(*CResourceHandler::get()->getResourceName(file));
 			mapInfo.date = std::asctime(std::localtime(&time));
 
 			// If multi mode then only multi games, otherwise single
@@ -1362,9 +1362,9 @@ void SelectionTab::select( int position )
 
 	if(txt)
 	{
-		std::string filename = *CResourceHandler::get("local")->getResourceName(
+		auto filename = *CResourceHandler::get("local")->getResourceName(
 								   ResourceID(curItems[py]->fileURI, EResType::CLIENT_SAVEGAME));
-		txt->setText(CFileInfo(filename).getBaseName());
+		txt->setText(filename.stem().string());
 	}
 
 	onSelect(curItems[py]);
@@ -1487,8 +1487,8 @@ void SelectionTab::printMaps(SDL_Surface *to)
 		}
 		else
 		{
-			name = CFileInfo(*CResourceHandler::get("local")->getResourceName(
-								 ResourceID(currentItem->fileURI, EResType::CLIENT_SAVEGAME))).getBaseName();
+			name = CResourceHandler::get("local")->getResourceName(
+								 ResourceID(currentItem->fileURI, EResType::CLIENT_SAVEGAME))->stem().string();
 		}
 
 		//print name

+ 29 - 29
client/Client.cpp

@@ -59,8 +59,8 @@ template <typename T> class CApplyOnCL;
 class CBaseForCLApply
 {
 public:
-	virtual void applyOnClAfter(CClient *cl, void *pack) const =0; 
-	virtual void applyOnClBefore(CClient *cl, void *pack) const =0; 
+	virtual void applyOnClAfter(CClient *cl, void *pack) const =0;
+	virtual void applyOnClBefore(CClient *cl, void *pack) const =0;
 	virtual ~CBaseForCLApply(){}
 
 	template<typename U> static CBaseForCLApply *getApplier(const U * t=nullptr)
@@ -144,7 +144,7 @@ void CClient::waitForMoveAndSend(PlayerColor color)
 		{
 			logNetwork->traceStream() << "Send battle action to server: " << ba;
 			MakeAction temp_action(ba);
-			sendRequest(&temp_action, color);			
+			sendRequest(&temp_action, color);
 		}
 		return;
 	}
@@ -169,8 +169,8 @@ void CClient::run()
 		while(!terminate)
 		{
 			CPack *pack = serv->retreivePack(); //get the package from the server
-			
-			if (terminate) 
+
+			if (terminate)
 			{
 				vstd::clear_pointer(pack);
 				break;
@@ -178,10 +178,10 @@ void CClient::run()
 
 			handlePack(pack);
 		}
-	} 
+	}
 	//catch only asio exceptions
 	catch (const boost::system::system_error& e)
-	{	
+	{
         logNetwork->errorStream() << "Lost connection to server, ending listening thread!";
         logNetwork->errorStream() << e.what();
 		if(!terminate) //rethrow (-> boom!) only if closing connection was unexpected
@@ -267,8 +267,8 @@ void CClient::loadGame(const std::string & fname, const bool server, const std::
 	std::unique_ptr<CLoadFile> loader;
 	try
 	{
-		std::string clientSaveName = *CResourceHandler::get("local")->getResourceName(ResourceID(fname, EResType::CLIENT_SAVEGAME));
-		std::string controlServerSaveName;
+		boost::filesystem::path clientSaveName = *CResourceHandler::get("local")->getResourceName(ResourceID(fname, EResType::CLIENT_SAVEGAME));
+		boost::filesystem::path controlServerSaveName;
 
 		if (CResourceHandler::get("local")->existsResource(ResourceID(fname, EResType::SERVER_SAVEGAME)))
 		{
@@ -276,8 +276,8 @@ void CClient::loadGame(const std::string & fname, const bool server, const std::
 		}
 		else// create entry for server savegame. Triggered if save was made after launch and not yet present in res handler
 		{
-			controlServerSaveName = clientSaveName.substr(0, clientSaveName.find_last_of(".")) + ".vsgm1";
-			CResourceHandler::get("local")->createResource(controlServerSaveName, true);
+			controlServerSaveName = boost::filesystem::path(clientSaveName).replace_extension(".vsgm1");
+			CResourceHandler::get("local")->createResource(controlServerSaveName.string(), true);
 		}
 
 		if(clientSaveName.empty())
@@ -320,7 +320,7 @@ void CClient::loadGame(const std::string & fname, const bool server, const std::
          *serv << ui8(3) << ui8(loadNumPlayers); //load game; one client if single-player
          *serv << fname;
          *serv >> pom8;
-         if(pom8) 
+         if(pom8)
               throw std::runtime_error("Server cannot open the savegame!");
          else
               logNetwork->infoStream() << "Server opened savegame properly.";
@@ -376,7 +376,7 @@ void CClient::newGame( CConnection *con, StartInfo *si )
 {
 	enum {SINGLE, HOST, GUEST} networkMode = SINGLE;
 
-	if (con == nullptr) 
+	if (con == nullptr)
 	{
 		CServerHandler sh;
 		serv = sh.connectToServer();
@@ -459,7 +459,7 @@ void CClient::newGame( CConnection *con, StartInfo *si )
 				logNetwork->infoStream() << boost::format("Player %s will be lead by %s") % color % AiToGive;
 				installNewPlayerInterface(CDynLibHandler::getNewAI(AiToGive), color);
 			}
-			else 
+			else
 			{
 				installNewPlayerInterface(std::make_shared<CPlayerInterface>(color), color);
 				humanPlayers++;
@@ -502,7 +502,7 @@ void CClient::newGame( CConnection *con, StartInfo *si )
 // 		nm->giveActionCB(this);
 // 		nm->giveInfoCB(this);
 // 		nm->init();
-// 
+//
 // 		erm = nm; //something tells me that there'll at most one module and it'll be ERM
 // 	}
 }
@@ -510,7 +510,7 @@ void CClient::newGame( CConnection *con, StartInfo *si )
 void CClient::serialize(COSer & h, const int version)
 {
 	assert(h.saving);
-	h & hotSeat;	
+	h & hotSeat;
 	{
 		ui8 players = playerint.size();
 		h & players;
@@ -520,7 +520,7 @@ void CClient::serialize(COSer & h, const int version)
 			LOG_TRACE_PARAMS(logGlobal, "Saving player %s interface", i->first);
 			assert(i->first == i->second->playerID);
 			h & i->first & i->second->dllName & i->second->human;
-			i->second->saveGame(h, version); 			
+			i->second->saveGame(h, version);
 		}
 	}
 }
@@ -536,7 +536,7 @@ void CClient::serialize(CISer & h, const int version)
 		for(int i=0; i < players; i++)
 		{
 			std::string dllname;
-			PlayerColor pid; 
+			PlayerColor pid;
 			bool isHuman = false;
 
 			h & pid & dllname & isHuman;
@@ -548,7 +548,7 @@ void CClient::serialize(CISer & h, const int version)
 				if(pid == PlayerColor::NEUTRAL)
 				{
 					installNewBattleInterface(CDynLibHandler::getNewBattleAI(dllname), pid);
-					//TODO? consider serialization 
+					//TODO? consider serialization
 					continue;
 				}
 				else
@@ -589,7 +589,7 @@ void CClient::serialize(COSer & h, const int version, const std::set<PlayerColor
 			LOG_TRACE_PARAMS(logGlobal, "Saving player %s interface", i->first);
 			assert(i->first == i->second->playerID);
 			h & i->first & i->second->dllName & i->second->human;
-			i->second->saveGame(h, version); 			
+			i->second->saveGame(h, version);
 		}
 	}
 }
@@ -605,7 +605,7 @@ void CClient::serialize(CISer & h, const int version, const std::set<PlayerColor
 		for(int i=0; i < players; i++)
 		{
 			std::string dllname;
-			PlayerColor pid; 
+			PlayerColor pid;
 			bool isHuman = false;
 
 			h & pid & dllname & isHuman;
@@ -618,7 +618,7 @@ void CClient::serialize(CISer & h, const int version, const std::set<PlayerColor
 				{
                     if(playerIDs.count(pid))
                        installNewBattleInterface(CDynLibHandler::getNewBattleAI(dllname), pid);
-					//TODO? consider serialization 
+					//TODO? consider serialization
 					continue;
 				}
 				else
@@ -640,7 +640,7 @@ void CClient::serialize(CISer & h, const int version, const std::set<PlayerColor
             if(playerIDs.count(pid))
                  installNewPlayerInterface(nInt, pid);
 
-            nInt->loadGame(h, version);       
+            nInt->loadGame(h, version);
 		}
 
 		if(playerIDs.count(PlayerColor::NEUTRAL))
@@ -714,7 +714,7 @@ void CClient::battleStarted(const BattleInfo * info)
 {
 	for(auto &battleCb : battleCallbacks)
 	{
-		if(vstd::contains_if(info->sides, [&](const SideInBattle& side) {return side.color == battleCb.first; })  
+		if(vstd::contains_if(info->sides, [&](const SideInBattle& side) {return side.color == battleCb.first; })
 			||  battleCb.first >= PlayerColor::PLAYER_LIMIT)
 		{
 			battleCb.second->setBattle(info);
@@ -742,7 +742,7 @@ void CClient::battleStarted(const BattleInfo * info)
 	{
 		boost::unique_lock<boost::recursive_mutex> un(*LOCPLINT->pim);
 		auto bi = new CBattleInterface(leftSide.armyObject, rightSide.armyObject, leftSide.hero, rightSide.hero,
-			Rect((screen->w - 800)/2, 
+			Rect((screen->w - 800)/2,
 			     (screen->h - 600)/2, 800, 600), att, def);
 
 		GH.pushInt(bi);
@@ -805,7 +805,7 @@ void CClient::commenceTacticPhaseForInt(std::shared_ptr<CBattleGameInterface> ba
 	catch(...)
 	{
 		handleException();
-	}	
+	}
 }
 
 void CClient::invalidatePaths()
@@ -889,7 +889,7 @@ void CClient::installNewBattleInterface(std::shared_ptr<CBattleGameInterface> ba
 	boost::unique_lock<boost::recursive_mutex> un(*LOCPLINT->pim);
 	PlayerColor colorUsed = color.get_value_or(PlayerColor::UNFLAGGABLE);
 
-	if(!color) 
+	if(!color)
 		privilagedBattleEventReceivers.push_back(battleInterface);
 
 	battleints[colorUsed] = battleInterface;
@@ -961,7 +961,7 @@ CConnection * CServerHandler::connectToServer()
 #endif
 
 	th.update(); //put breakpoint here to attach to server before it does something stupid
-    
+
 	CConnection *ret = justConnectToServer(settings["server"]["server"].String(), port);
 
 	if(verbose)
@@ -1033,7 +1033,7 @@ CConnection * CServerHandler::justConnectToServer(const std::string &host, const
 		try
 		{
             logNetwork->infoStream() << "Establishing connection...";
-			ret = new CConnection(	host.size() ? host : settings["server"]["server"].String(), 
+			ret = new CConnection(	host.size() ? host : settings["server"]["server"].String(),
 									realPort,
 									NAME);
 		}

+ 4 - 1
client/VCMI_client.cbp

@@ -3,7 +3,7 @@
 	<FileVersion major="1" minor="6" />
 	<Project>
 		<Option title="VCMI_client" />
-		<Option pch_mode="2" />
+		<Option pch_mode="0" />
 		<Option compiler="gcc" />
 		<Build>
 			<Target title="Debug-win32">
@@ -62,6 +62,7 @@
 		<Compiler>
 			<Add option="-Wextra" />
 			<Add option="-Wall" />
+			<Add option="-std=gnu++11" />
 			<Add option="-fexceptions" />
 			<Add option="-Wpointer-arith" />
 			<Add option="-Wno-switch" />
@@ -70,7 +71,9 @@
 			<Add option="-Wno-overloaded-virtual" />
 			<Add option="-fpermissive" />
 			<Add option="-DBOOST_THREAD_USE_LIB" />
+			<Add option="-DBOOST_SYSTEM_NO_DEPRECATED" />
 			<Add option="-D_WIN32_WINNT=0x0501" />
+			<Add option="-D_WIN32" />
 			<Add directory="$(#boost.include)" />
 			<Add directory="../include" />
 			<Add directory="../client" />

+ 10 - 1
launcher/StdInc.h

@@ -17,4 +17,13 @@ inline QString pathToQString(const boost::filesystem::path & path)
 #else
 	return QString::fromStdString(path.string());
 #endif
-}
+}
+
+inline boost::filesystem::path qstringToPath(const QString & path)
+{
+#ifdef VCMI_WINDOWS
+	return boost::filesystem::path(path.toStdWString());
+#else
+	return boost::filesystem::path(path.toUtf8().data());
+#endif
+}

+ 103 - 0
launcher/VCMI_launcher.cbp

@@ -0,0 +1,103 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_project_file>
+	<FileVersion major="1" minor="6" />
+	<Project>
+		<Option title="VCMI_launcher" />
+		<Option pch_mode="0" />
+		<Option compiler="gcc" />
+		<Build>
+			<Target title="Debug Win32">
+				<Option output="../VCMI_launcher" prefix_auto="1" extension_auto="1" />
+				<Option working_dir="../" />
+				<Option object_output=".objs/debug" />
+				<Option type="0" />
+				<Option compiler="gcc" />
+				<Compiler>
+					<Add option="-g" />
+				</Compiler>
+			</Target>
+			<Target title="Release Win32">
+				<Option output="../VCMI_launcher" prefix_auto="1" extension_auto="1" />
+				<Option working_dir="../" />
+				<Option object_output=".objs/release" />
+				<Option type="0" />
+				<Option compiler="gcc" />
+				<Compiler>
+					<Add option="-O3" />
+					<Add option="-flto" />
+				</Compiler>
+				<Linker>
+					<Add option="-s" />
+					<Add option="-flto" />
+				</Linker>
+			</Target>
+		</Build>
+		<Compiler>
+			<Add option="-Wextra" />
+			<Add option="-Wall" />
+			<Add option="-std=gnu++11" />
+			<Add option="-DBOOST_SYSTEM_NO_DEPRECATED" />
+			<Add option="-D_WIN32" />
+			<Add directory="." />
+			<Add directory="../include" />
+			<Add directory="$(#boost.include)" />
+			<Add directory="$(#qt.include)" />
+			<Add directory="$(#qt.include)/QtGui" />
+			<Add directory="$(#qt.include)/QtCore" />
+			<Add directory="$(#qt.include)/QtWidgets" />
+		</Compiler>
+		<Linker>
+			<Add option="-lVCMI_lib" />
+			<Add option="-lQt5Core" />
+			<Add option="-lQt5Gui" />
+			<Add option="-lQt5Widgets" />
+			<Add option="-lQt5Network" />
+			<Add option="-lboost_filesystem$(#boost.libsuffix)" />
+			<Add option="-lboost_system$(#boost.libsuffix)" />
+			<Add directory="../" />
+			<Add directory="$(#qt.lib)" />
+			<Add directory="$(#boost.lib)" />
+		</Linker>
+		<Unit filename="StdInc.cpp" />
+		<Unit filename="StdInc.h">
+			<Option compile="1" />
+			<Option weight="0" />
+		</Unit>
+		<Unit filename="VCMI_launcher.rc">
+			<Option compilerVar="WINDRES" />
+		</Unit>
+		<Unit filename="jsonutils.cpp" />
+		<Unit filename="jsonutils.h" />
+		<Unit filename="launcherdirs.cpp" />
+		<Unit filename="launcherdirs.h" />
+		<Unit filename="main.cpp" />
+		<Unit filename="mainwindow_moc.cpp" />
+		<Unit filename="mainwindow_moc.h" />
+		<Unit filename="modManager/cdownloadmanager_moc.cpp" />
+		<Unit filename="modManager/cdownloadmanager_moc.h" />
+		<Unit filename="modManager/cmodlist.cpp" />
+		<Unit filename="modManager/cmodlist.h" />
+		<Unit filename="modManager/cmodlistmodel_moc.cpp" />
+		<Unit filename="modManager/cmodlistmodel_moc.h" />
+		<Unit filename="modManager/cmodlistview_moc.cpp" />
+		<Unit filename="modManager/cmodlistview_moc.h" />
+		<Unit filename="modManager/cmodmanager.cpp" />
+		<Unit filename="modManager/cmodmanager.h" />
+		<Unit filename="modManager/imageviewer_moc.cpp" />
+		<Unit filename="modManager/imageviewer_moc.h" />
+		<Unit filename="modManager/qrc_cdownloadmanager_moc.cpp" />
+		<Unit filename="modManager/qrc_cmodlistmodel_moc.cpp" />
+		<Unit filename="modManager/qrc_cmodlistview_moc.cpp" />
+		<Unit filename="modManager/qrc_imageviewer_moc.cpp" />
+		<Unit filename="qrc_mainwindow_moc.cpp" />
+		<Unit filename="settingsView/csettingsview_moc.cpp" />
+		<Unit filename="settingsView/csettingsview_moc.h" />
+		<Unit filename="settingsView/qrc_csettingsview_moc.cpp" />
+		<Extensions>
+			<code_completion />
+			<envvars />
+			<debugger />
+			<lib_finder disable_auto="1" />
+		</Extensions>
+	</Project>
+</CodeBlocks_project_file>

+ 2 - 2
launcher/jsonutils.cpp

@@ -1,5 +1,6 @@
 #include "StdInc.h"
 #include "jsonutils.h"
+#include "../lib/filesystem/FileStream.h"
 
 static QVariantMap JsonToMap(const JsonMap & json)
 {
@@ -96,8 +97,7 @@ JsonNode toJson(QVariant object)
 
 void JsonToFile(QString filename, QVariant object)
 {
-	std::ofstream file(filename.toUtf8().data(), std::ofstream::binary);
-
+	FileStream file(qstringToPath(filename), std::ios::out | std::ios_base::binary);
 	file << toJson(object);
 }
 

+ 1 - 0
launcher/modManager/cmodlist.h

@@ -2,6 +2,7 @@
 
 #include <QVariantMap>
 #include <QVariant>
+#include <QVector>
 
 class JsonNode;
 

+ 2 - 2
launcher/modManager/cmodlistview_moc.h

@@ -1,6 +1,6 @@
 #pragma once
 
-#include "../../Global.h"
+#include "StdInc.h"
 #include "../../lib/CConfigHandler.h"
 
 namespace Ui {
@@ -55,7 +55,7 @@ class CModListView : public QWidget
 public:
 	explicit CModListView(QWidget *parent = 0);
 	~CModListView();
-	
+
 	void showModInfo();
 	void hideModInfo();
 	void loadScreenshots();

+ 5 - 5
launcher/modManager/cmodmanager.cpp

@@ -11,7 +11,7 @@
 
 static QString detectModArchive(QString path, QString modName)
 {
-	auto files = ZipArchive::listFiles(path.toUtf8().data());
+	auto files = ZipArchive::listFiles(qstringToPath(path));
 
 	QString modDirName;
 
@@ -69,8 +69,8 @@ void CModManager::loadMods()
 		ResourceID resID(CModInfo::getModFile(modname));
 		if (CResourceHandler::get()->existsResource(resID))
 		{
-			std::string name = *CResourceHandler::get()->getResourceName(resID);
-			auto mod = JsonUtils::JsonFromFile(QString::fromUtf8(name.c_str()));
+			boost::filesystem::path name = *CResourceHandler::get()->getResourceName(resID);
+			auto mod = JsonUtils::JsonFromFile(pathToQString(name));
 			localMods.insert(QString::fromUtf8(modname.c_str()).toLower(), mod);
 		}
 	}
@@ -243,7 +243,7 @@ bool CModManager::doInstallMod(QString modname, QString archivePath)
 	if (!modDirName.size())
 		return addError(modname, "Mod archive is invalid or corrupted");
 
-	if (!ZipArchive::extract(archivePath.toUtf8().data(), destDir.toUtf8().data()))
+	if (!ZipArchive::extract(qstringToPath(archivePath), qstringToPath(destDir)))
 	{
 		QDir(destDir + modDirName).removeRecursively();
 		return addError(modname, "Failed to extract mod data");
@@ -262,7 +262,7 @@ bool CModManager::doUninstallMod(QString modname)
 {
 	ResourceID resID(std::string("Mods/") + modname.toUtf8().data(), EResType::DIRECTORY);
 	// Get location of the mod, in case-insensitive way
-	QString modDir = QString::fromUtf8(CResourceHandler::get()->getResourceName(resID)->c_str());
+	QString modDir = pathToQString(*CResourceHandler::get()->getResourceName(resID));
 
 	if (!QDir(modDir).exists())
 		return addError(modname, "Data with this mod was not found");

+ 4 - 2
launcher/settingsView/csettingsview_moc.h

@@ -1,5 +1,7 @@
 #pragma once
 
+#include "StdInc.h"
+
 namespace Ui {
 	class CSettingsView;
 }
@@ -7,13 +9,13 @@ namespace Ui {
 class CSettingsView : public QWidget
 {
 	Q_OBJECT
-	
+
 public:
 	explicit CSettingsView(QWidget *parent = 0);
 	~CSettingsView();
 
 	void loadSettings();
-	
+
 private slots:
 	void on_comboBoxResolution_currentIndexChanged(const QString &arg1);
 

+ 6 - 5
lib/CConfigHandler.cpp

@@ -2,6 +2,7 @@
 #include "CConfigHandler.h"
 
 #include "../lib/filesystem/Filesystem.h"
+#include "../lib/filesystem/FileStream.h"
 #include "../lib/GameConstants.h"
 #include "../lib/VCMIDirs.h"
 
@@ -80,7 +81,7 @@ void SettingsStorage::invalidateNode(const std::vector<std::string> &changedPath
 	savedConf.Struct().erase("session");
 	JsonUtils::minimize(savedConf, "vcmi:settings");
 
-	std::ofstream file(*CResourceHandler::get()->getResourceName(ResourceID("config/settings.json")), std::ofstream::trunc);
+	FileStream file(*CResourceHandler::get()->getResourceName(ResourceID("config/settings.json")), std::ofstream::out | std::ofstream::trunc);
 	file << savedConf;
 }
 
@@ -173,7 +174,7 @@ JsonNode& Settings::operator [](std::string value)
 {
 	return node[value];
 }
-// 
+//
 // template DLL_LINKAGE struct SettingsStorage::NodeAccessor<SettingsListener>;
 // template DLL_LINKAGE struct SettingsStorage::NodeAccessor<Settings>;
 
@@ -214,14 +215,14 @@ void config::CConfigHandler::init()
 	const JsonNode config(ResourceID("config/resolutions.json"));
 	const JsonVector &guisettings_vec = config["GUISettings"].Vector();
 
-	for(const JsonNode &g : guisettings_vec) 
+	for(const JsonNode &g : guisettings_vec)
 	{
 		std::pair<int,int> curRes(g["resolution"]["x"].Float(), g["resolution"]["y"].Float());
 		GUIOptions *current = &conf.guiOptions[curRes];
-		
+
 		current->ac.inputLineLength = g["InGameConsole"]["maxInputPerLine"].Float();
 		current->ac.outputLineLength = g["InGameConsole"]["maxOutputPerLine"].Float();
-		
+
 		current->ac.advmapX = g["AdvMap"]["x"].Float();
 		current->ac.advmapY = g["AdvMap"]["y"].Float();
 		current->ac.advmapW = g["AdvMap"]["width"].Float();

+ 1 - 0
lib/CMakeLists.txt

@@ -17,6 +17,7 @@ set(lib_SRCS
 		filesystem/CFileInputStream.cpp
 		filesystem/CZipLoader.cpp
 		filesystem/Filesystem.cpp
+		filesystem/FileStream.cpp
 		filesystem/ResourceID.cpp
 
 		mapObjects/CArmedInstance.cpp

+ 2 - 1
lib/CModHandler.cpp

@@ -2,6 +2,7 @@
 #include "CModHandler.h"
 #include "mapObjects/CObjectClassesHandler.h"
 #include "JsonNode.h"
+#include "filesystem/FileStream.h"
 #include "filesystem/Filesystem.h"
 #include "filesystem/AdapterLoaders.h"
 #include "filesystem/CFilesystemLoader.h"
@@ -901,6 +902,6 @@ void CModHandler::afterLoad()
 	}
 	modSettings["core"] = coreMod.saveLocalData();
 
-	std::ofstream file(*CResourceHandler::get()->getResourceName(ResourceID("config/modSettings.json")), std::ofstream::trunc);
+	FileStream file(*CResourceHandler::get()->getResourceName(ResourceID("config/modSettings.json")), std::ofstream::out | std::ofstream::trunc);
 	file << modSettings;
 }

+ 6 - 5
lib/Connection.cpp

@@ -4,6 +4,7 @@
 #include "registerTypes/RegisterTypes.h"
 #include "mapping/CMap.h"
 #include "CGameState.h"
+#include "filesystem/FileStream.h"
 
 #include <boost/asio.hpp>
 
@@ -282,7 +283,7 @@ void CConnection::enableSmartVectorMemberSerializatoin()
 	CSerializer::smartVectorMembersSerialization = true;
 }
 
-CSaveFile::CSaveFile( const std::string &fname ): serializer(this)
+CSaveFile::CSaveFile( const boost::filesystem::path &fname ): serializer(this)
 {
 	registerTypes(serializer);
 	openNextFile(fname);
@@ -298,12 +299,12 @@ int CSaveFile::write( const void * data, unsigned size )
 	return size;
 }
 
-void CSaveFile::openNextFile(const std::string &fname)
+void CSaveFile::openNextFile(const boost::filesystem::path &fname)
 {
 	fName = fname;
 	try
 	{
-		sfile = make_unique<std::ofstream>(fname.c_str(), std::ios::binary);
+		sfile = make_unique<FileStream>(fname, std::ios::out | std::ios::binary);
 		sfile->exceptions(std::ifstream::failbit | std::ifstream::badbit); //we throw a lot anyway
 
 		if(!(*sfile))
@@ -364,7 +365,7 @@ void CLoadFile::openNextFile(const boost::filesystem::path & fname, int minimalV
 	try
 	{
 		fName = fname.string();
-		sfile = make_unique<boost::filesystem::ifstream>(fname, std::ios::binary);
+		sfile = make_unique<FileStream>(fname, std::ios::in | std::ios::binary);
 		sfile->exceptions(std::ifstream::failbit | std::ifstream::badbit); //we throw a lot anyway
 
 		if(!(*sfile))
@@ -569,7 +570,7 @@ void CSerializer::addStdVecItems(CGameState *gs, LibClasses *lib)
 	smartVectorMembersSerialization = true;
 }
 
-CLoadIntegrityValidator::CLoadIntegrityValidator( const std::string &primaryFileName, const std::string &controlFileName, int minimalVersion /*= version*/ )
+CLoadIntegrityValidator::CLoadIntegrityValidator( const boost::filesystem::path &primaryFileName, const boost::filesystem::path &controlFileName, int minimalVersion /*= version*/ )
 	: serializer(this), foundDesync(false)
 {
 	registerTypes(serializer);

+ 8 - 7
lib/Connection.h

@@ -39,6 +39,7 @@ class CGameState;
 class CCreature;
 class LibClasses;
 class CHero;
+class FileStream;
 struct CPack;
 extern DLL_LINKAGE LibClasses * VLC;
 namespace mpl = boost::mpl;
@@ -1550,14 +1551,14 @@ public:
 
 	COSer serializer;
 
-	std::string fName;
-	std::unique_ptr<std::ofstream> sfile;
+	boost::filesystem::path fName;
+	std::unique_ptr<FileStream> sfile;
 
-	CSaveFile(const std::string &fname); //throws!
+	CSaveFile(const boost::filesystem::path &fname); //throws!
 	~CSaveFile();
 	int write(const void * data, unsigned size) override;
 
-	void openNextFile(const std::string &fname); //throws!
+	void openNextFile(const boost::filesystem::path &fname); //throws!
 	void clear();
     void reportState(CLogger * out) override;
 
@@ -1577,8 +1578,8 @@ class DLL_LINKAGE CLoadFile
 public:
 	CISer serializer;
 
-	std::string fName;
-	std::unique_ptr<boost::filesystem::ifstream> sfile;
+	boost::filesystem::path fName;
+	std::unique_ptr<FileStream> sfile;
 
 	CLoadFile(const boost::filesystem::path & fname, int minimalVersion = version); //throws!
 	~CLoadFile();
@@ -1606,7 +1607,7 @@ public:
 	std::unique_ptr<CLoadFile> primaryFile, controlFile;
 	bool foundDesync;
 
-	CLoadIntegrityValidator(const std::string &primaryFileName, const std::string &controlFileName, int minimalVersion = version); //throws!
+	CLoadIntegrityValidator(const boost::filesystem::path &primaryFileName, const boost::filesystem::path &controlFileName, int minimalVersion = version); //throws!
 
 	int read( void * data, unsigned size) override; //throws!
 	void checkMagicBytes(const std::string &text);

+ 7 - 4
lib/VCMI_lib.cbp

@@ -4,7 +4,7 @@
 	<Project>
 		<Option title="VCMI_lib" />
 		<Option execution_dir="D:/projects/vcmi/engine/VCMI_lib/" />
-		<Option pch_mode="2" />
+		<Option pch_mode="0" />
 		<Option compiler="gcc" />
 		<Build>
 			<Target title="Debug-win32">
@@ -17,8 +17,8 @@
 				<Option run_host_application_in_terminal="1" />
 				<Option createStaticLib="1" />
 				<Compiler>
-					<Add option="-Og" />
 					<Add option="-g" />
+					<Add option="-Og" />
 					<Add directory="$(#zlib.include)" />
 				</Compiler>
 				<Linker>
@@ -62,7 +62,6 @@
 					<Add option="-lboost_locale$(#boost.libsuffix)" />
 					<Add option="-lboost_date_time$(#boost.libsuffix)" />
 					<Add option="-liconv" />
-					<Add option="-ldbghelp" />
 					<Add directory="$(#sdl2.lib)" />
 					<Add directory="$(#boost.lib32)" />
 					<Add directory="$(#zlib.lib)" />
@@ -103,6 +102,7 @@
 		<Compiler>
 			<Add option="-Wextra" />
 			<Add option="-Wall" />
+			<Add option="-std=gnu++11" />
 			<Add option="-fexceptions" />
 			<Add option="-Wpointer-arith" />
 			<Add option="-Wno-switch" />
@@ -112,7 +112,9 @@
 			<Add option="-Wno-unused-local-typedefs" />
 			<Add option="-DVCMI_DLL" />
 			<Add option="-DBOOST_THREAD_USE_LIB" />
+			<Add option="-DBOOST_SYSTEM_NO_DEPRECATED" />
 			<Add option="-D_WIN32_WINNT=0x0501" />
+			<Add option="-D_WIN32" />
 			<Add directory="$(#boost.include)" />
 			<Add directory="../include" />
 			<Add directory="../lib" />
@@ -200,7 +202,6 @@
 		<Unit filename="StartInfo.h" />
 		<Unit filename="StdInc.h">
 			<Option weight="0" />
-			<Option target="Debug-win64" />
 		</Unit>
 		<Unit filename="StringConstants.h" />
 		<Unit filename="UnlockGuard.h" />
@@ -227,6 +228,8 @@
 		<Unit filename="filesystem/CMemoryStream.h" />
 		<Unit filename="filesystem/CZipLoader.cpp" />
 		<Unit filename="filesystem/CZipLoader.h" />
+		<Unit filename="filesystem/FileStream.cpp" />
+		<Unit filename="filesystem/FileStream.h" />
 		<Unit filename="filesystem/Filesystem.cpp" />
 		<Unit filename="filesystem/Filesystem.h" />
 		<Unit filename="filesystem/ISimpleResourceLoader.h" />

+ 3 - 3
lib/filesystem/AdapterLoaders.cpp

@@ -27,7 +27,7 @@ std::string CMappedFileLoader::getMountPoint() const
 	return ""; // does not have any meaning with this type of data source
 }
 
-boost::optional<std::string> CMappedFileLoader::getResourceName(const ResourceID & resourceName) const
+boost::optional<boost::filesystem::path> CMappedFileLoader::getResourceName(const ResourceID & resourceName) const
 {
 	return CResourceHandler::get()->getResourceName(fileList.at(resourceName));
 }
@@ -80,11 +80,11 @@ std::string CFilesystemList::getMountPoint() const
 	return "";
 }
 
-boost::optional<std::string> CFilesystemList::getResourceName(const ResourceID & resourceName) const
+boost::optional<boost::filesystem::path> CFilesystemList::getResourceName(const ResourceID & resourceName) const
 {
 	if (existsResource(resourceName))
 		return getResourcesWithName(resourceName).back()->getResourceName(resourceName);
-	return boost::optional<std::string>();
+	return boost::optional<boost::filesystem::path>();
 }
 
 std::set<std::string> CFilesystemList::getResourceNames(const ResourceID & resourceName) const

+ 4 - 4
lib/filesystem/AdapterLoaders.h

@@ -41,7 +41,7 @@ public:
 	std::unique_ptr<CInputStream> load(const ResourceID & resourceName) const override;
 	bool existsResource(const ResourceID & resourceName) const override;
 	std::string getMountPoint() const override;
-	boost::optional<std::string> getResourceName(const ResourceID & resourceName) const override;
+	boost::optional<boost::filesystem::path> getResourceName(const ResourceID & resourceName) const override;
 	std::unordered_set<ResourceID> getFilteredFiles(std::function<bool(const ResourceID &)> filter) const override;
 
 private:
@@ -59,8 +59,8 @@ class DLL_LINKAGE CFilesystemList : public ISimpleResourceLoader
 	std::set<ISimpleResourceLoader *> writeableLoaders;
 
 	//FIXME: this is only compile fix, should be removed in the end
-	CFilesystemList(CFilesystemList &) = delete;
-	CFilesystemList &operator=(CFilesystemList &) = delete;
+	CFilesystemList(CFilesystemList &) = delete;
+	CFilesystemList &operator=(CFilesystemList &) = delete;
 
 public:
 	CFilesystemList();
@@ -70,7 +70,7 @@ public:
 	std::unique_ptr<CInputStream> load(const ResourceID & resourceName) const override;
 	bool existsResource(const ResourceID & resourceName) const override;
 	std::string getMountPoint() const override;
-	boost::optional<std::string> getResourceName(const ResourceID & resourceName) const override;
+	boost::optional<boost::filesystem::path> getResourceName(const ResourceID & resourceName) const override;
 	std::set<std::string> getResourceNames(const ResourceID & resourceName) const override;
 	std::unordered_set<ResourceID> getFilteredFiles(std::function<bool(const ResourceID &)> filter) const override;
 	bool createResource(std::string filename, bool update = false) override;

+ 7 - 21
lib/filesystem/CFileInputStream.cpp

@@ -4,39 +4,25 @@
 #include "CFileInfo.h"
 
 CFileInputStream::CFileInputStream(const boost::filesystem::path & file, si64 start, si64 size)
+  : dataStart{start},
+	dataSize{size},
+	fileStream{file, std::ios::in | std::ios::binary}
 {
-	open(file, start, size);
-}
-
-CFileInputStream::CFileInputStream(const CFileInfo & file, si64 start, si64 size)
-{
-	open(file.getName(), start, size);
-}
-
-CFileInputStream::~CFileInputStream()
-{
-	fileStream.close();
-}
-
-void CFileInputStream::open(const boost::filesystem::path & file, si64 start, si64 size)
-{
-	fileStream.open(file, std::ios::in | std::ios::binary);
-
 	if (fileStream.fail())
 		throw std::runtime_error("File " + file.string() + " isn't available.");
 
-	dataStart = start;
-	dataSize = size;
-
 	if (dataSize == 0)
 	{
 		fileStream.seekg(0, std::ios::end);
 		dataSize = tell();
 	}
 
-	fileStream.seekg(start, std::ios::beg);
+	fileStream.seekg(dataStart, std::ios::beg);
 }
 
+CFileInputStream::CFileInputStream(const CFileInfo & file, si64 start, si64 size)
+	: CFileInputStream{file.getName(), start, size} {}
+
 si64 CFileInputStream::read(ui8 * data, si64 size)
 {
 	si64 origin = tell();

+ 8 - 19
lib/filesystem/CFileInputStream.h

@@ -11,6 +11,7 @@
  */
 
 #include "CInputStream.h"
+#include "FileStream.h"
 
 class CFileInfo;
 
@@ -23,22 +24,21 @@ public:
 	/**
 	 * C-tor. Opens the specified file.
 	 *
-	 * @see CFileInputStream::open
+	 * @param file Path to the file.
+	 * @param start - offset from file start where real data starts (e.g file on archive)
+	 * @param size - size of real data in file (e.g file on archive) or 0 to use whole file
+	 *
+	 * @throws std::runtime_error if file wasn't found
 	 */
 	CFileInputStream(const boost::filesystem::path & file, si64 start = 0, si64 size = 0);
 
 	/**
 	 * C-tor. Opens the specified file.
 	 *
-	 * @see CFileInputStream::open
+	 * @see CFileInputStream::CFileInputStream(const boost::filesystem::path &, si64, si64)
 	 */
 	CFileInputStream(const CFileInfo & file, si64 start=0, si64 size=0);
 
-	/**
-	 * D-tor. Calls the close method implicitely, if the file is still opened.
-	 */
-	~CFileInputStream();
-
 	/**
 	 * Reads n bytes from the stream into the data buffer.
 	 *
@@ -79,20 +79,9 @@ public:
 	si64 getSize() override;
 
 private:
-	/**
-	 * Opens a file. If a file is currently opened, it will be closed.
-	 *
-	 * @param file Path to the file.
-	 * @param start - offset from file start where real data starts (e.g file on archive)
-	 * @param size - size of real data in file (e.g file on archive) or 0 to use whole file
-	 *
-	 * @throws std::runtime_error if file wasn't found
-	 */
-	void open(const boost::filesystem::path & file, si64 start, si64 size);
-
 	si64 dataStart;
 	si64 dataSize;
 
 	/** Native c++ input file stream object. */
-	boost::filesystem::ifstream fileStream;
+	FileStream fileStream;
 };

+ 4 - 4
lib/filesystem/CFilesystemLoader.cpp

@@ -3,6 +3,7 @@
 
 #include "CFileInfo.h"
 #include "CFileInputStream.h"
+#include "FileStream.h"
 
 namespace bfs = boost::filesystem;
 
@@ -32,11 +33,11 @@ std::string CFilesystemLoader::getMountPoint() const
 	return mountPoint;
 }
 
-boost::optional<std::string> CFilesystemLoader::getResourceName(const ResourceID & resourceName) const
+boost::optional<boost::filesystem::path> CFilesystemLoader::getResourceName(const ResourceID & resourceName) const
 {
 	assert(existsResource(resourceName));
 
-	return (baseDirectory / fileList.at(resourceName)).string();
+	return baseDirectory / fileList.at(resourceName);
 }
 
 std::unordered_set<ResourceID> CFilesystemLoader::getFilteredFiles(std::function<bool(const ResourceID &)> filter) const
@@ -68,8 +69,7 @@ bool CFilesystemLoader::createResource(std::string filename, bool update)
 
 	if (!update)
 	{
-		bfs::ofstream newfile(baseDirectory / filename);
-		if (!newfile.good())
+		if (!FileStream::CreateFile(baseDirectory / filename))
 			return false;
 	}
 	fileList[resID] = filename;

+ 1 - 1
lib/filesystem/CFilesystemLoader.h

@@ -38,7 +38,7 @@ public:
 	bool existsResource(const ResourceID & resourceName) const override;
 	std::string getMountPoint() const override;
 	bool createResource(std::string filename, bool update = false) override;
-	boost::optional<std::string> getResourceName(const ResourceID & resourceName) const override;
+	boost::optional<boost::filesystem::path> getResourceName(const ResourceID & resourceName) const override;
 	std::unordered_set<ResourceID> getFilteredFiles(std::function<bool(const ResourceID &)> filter) const override;
 
 private:

+ 29 - 28
lib/filesystem/CZipLoader.cpp

@@ -1,6 +1,7 @@
 #include "StdInc.h"
-#include "../../Global.h"
+//#include "../../Global.h"
 #include "CZipLoader.h"
+#include "FileStream.h"
 
 #include "../ScopeGuard.h"
 
@@ -14,10 +15,10 @@
  *
  */
 
-CZipStream::CZipStream(const std::string & archive, unz_file_pos filepos)
+CZipStream::CZipStream(const boost::filesystem::path & archive, unz64_file_pos filepos)
 {
-	file = unzOpen(archive.c_str());
-	unzGoToFilePos(file, &filepos);
+	file = unzOpen2_64(archive.c_str(), FileStream::GetMinizipFilefunc());
+	unzGoToFilePos64(file, &filepos);
 	unzOpenCurrentFile(file);
 }
 
@@ -34,19 +35,19 @@ si64 CZipStream::readMore(ui8 * data, si64 size)
 
 si64 CZipStream::getSize()
 {
-	unz_file_info info;
-	unzGetCurrentFileInfo (file, &info, nullptr, 0, nullptr, 0, nullptr, 0);
+	unz_file_info64 info;
+	unzGetCurrentFileInfo64 (file, &info, nullptr, 0, nullptr, 0, nullptr, 0);
 	return info.uncompressed_size;
 }
 
 ui32 CZipStream::calculateCRC32()
 {
-	unz_file_info info;
-	unzGetCurrentFileInfo (file, &info, nullptr, 0, nullptr, 0, nullptr, 0);
+	unz_file_info64 info;
+	unzGetCurrentFileInfo64 (file, &info, nullptr, 0, nullptr, 0, nullptr, 0);
 	return info.crc;
 }
 
-CZipLoader::CZipLoader(const std::string & mountPoint, const std::string & archive):
+CZipLoader::CZipLoader(const std::string & mountPoint, const boost::filesystem::path & archive):
     archiveName(archive),
     mountPoint(mountPoint),
     files(listFiles(mountPoint, archive))
@@ -54,27 +55,27 @@ CZipLoader::CZipLoader(const std::string & mountPoint, const std::string & archi
 	logGlobal->traceStream() << "Zip archive loaded, " << files.size() << " files found";
 }
 
-std::unordered_map<ResourceID, unz_file_pos> CZipLoader::listFiles(const std::string & mountPoint, const std::string & archive)
+std::unordered_map<ResourceID, unz64_file_pos> CZipLoader::listFiles(const std::string & mountPoint, const boost::filesystem::path & archive)
 {
-	std::unordered_map<ResourceID, unz_file_pos> ret;
+	std::unordered_map<ResourceID, unz64_file_pos> ret;
 
-	unzFile file = unzOpen(archive.c_str());
+	unzFile file = unzOpen2_64(archive.c_str(), FileStream::GetMinizipFilefunc());
 
 	if (unzGoToFirstFile(file) == UNZ_OK)
 	{
 		do
 		{
-			unz_file_info info;
+			unz_file_info64 info;
 			std::vector<char> filename;
 			// Fill unz_file_info structure with current file info
-			unzGetCurrentFileInfo (file, &info, nullptr, 0, nullptr, 0, nullptr, 0);
+			unzGetCurrentFileInfo64 (file, &info, nullptr, 0, nullptr, 0, nullptr, 0);
 
 			filename.resize(info.size_filename);
 			// Get name of current file. Contrary to docs "info" parameter can't be null
-			unzGetCurrentFileInfo (file, &info, filename.data(), filename.size(), nullptr, 0, nullptr, 0);
+			unzGetCurrentFileInfo64 (file, &info, filename.data(), filename.size(), nullptr, 0, nullptr, 0);
 
 			std::string filenameString(filename.data(), filename.size());
-			unzGetFilePos(file, &ret[ResourceID(mountPoint + filenameString)]);
+			unzGetFilePos64(file, &ret[ResourceID(mountPoint + filenameString)]);
 		}
 		while (unzGoToNextFile(file) == UNZ_OK);
 	}
@@ -140,24 +141,24 @@ static bool extractCurrent(unzFile file, std::ostream & where)
 	return false;
 }
 
-std::vector<std::string> ZipArchive::listFiles(std::string filename)
+std::vector<std::string> ZipArchive::listFiles(boost::filesystem::path filename)
 {
 	std::vector<std::string> ret;
 
-	unzFile file = unzOpen(filename.c_str());
+	unzFile file = unzOpen2_64(filename.c_str(), FileStream::GetMinizipFilefunc());
 
 	if (unzGoToFirstFile(file) == UNZ_OK)
 	{
 		do
 		{
-			unz_file_info info;
+			unz_file_info64 info;
 			std::vector<char> filename;
 
-			unzGetCurrentFileInfo (file, &info, nullptr, 0, nullptr, 0, nullptr, 0);
+			unzGetCurrentFileInfo64 (file, &info, nullptr, 0, nullptr, 0, nullptr, 0);
 
 			filename.resize(info.size_filename);
 			// Get name of current file. Contrary to docs "info" parameter can't be null
-			unzGetCurrentFileInfo (file, &info, filename.data(), filename.size(), nullptr, 0, nullptr, 0);
+			unzGetCurrentFileInfo64 (file, &info, filename.data(), filename.size(), nullptr, 0, nullptr, 0);
 
 			ret.push_back(std::string(filename.data(), filename.size()));
 		}
@@ -168,29 +169,29 @@ std::vector<std::string> ZipArchive::listFiles(std::string filename)
 	return ret;
 }
 
-bool ZipArchive::extract(std::string from, std::string where)
+bool ZipArchive::extract(boost::filesystem::path from, boost::filesystem::path where)
 {
 	// Note: may not be fast enough for large archives (should NOT happen with mods)
 	// because locating each file by name may be slow. Unlikely slower than decompression though
 	return extract(from, where, listFiles(from));
 }
 
-bool ZipArchive::extract(std::string from, std::string where, std::vector<std::string> what)
+bool ZipArchive::extract(boost::filesystem::path from, boost::filesystem::path where, std::vector<std::string> what)
 {
-	unzFile archive = unzOpen(from.c_str());
+	unzFile archive = unzOpen2_64(from.c_str(), FileStream::GetMinizipFilefunc());
 
 	auto onExit = vstd::makeScopeGuard([&]()
 	{
 		unzClose(archive);
 	});
 
-	for (std::string & file : what)
+	for (const std::string & file : what)
 	{
 		if (unzLocateFile(archive, file.c_str(), 1) != UNZ_OK)
 			return false;
 
-		std::string fullName = where + '/' + file;
-		std::string fullPath = fullName.substr(0, fullName.find_last_of("/"));
+		const boost::filesystem::path fullName = where / file;
+		const boost::filesystem::path fullPath = fullName.parent_path();
 
 		boost::filesystem::create_directories(fullPath);
 		// directory. No file to extract
@@ -198,7 +199,7 @@ bool ZipArchive::extract(std::string from, std::string where, std::vector<std::s
 		if (boost::algorithm::ends_with(file, "/"))
 			continue;
 
-		std::ofstream destFile(fullName, std::ofstream::binary);
+		FileStream destFile(fullName, std::ios::out | std::ios::binary);
 		if (!destFile.good())
 			return false;
 

+ 8 - 8
lib/filesystem/CZipLoader.h

@@ -32,7 +32,7 @@ public:
 	 * @param archive path to archive to open
 	 * @param filepos position of file to open
 	 */
-	CZipStream(const std::string & archive, unz_file_pos filepos);
+	CZipStream(const boost::filesystem::path & archive, unz64_file_pos filepos);
 	~CZipStream();
 
 	si64 getSize() override;
@@ -44,14 +44,14 @@ protected:
 
 class DLL_LINKAGE CZipLoader : public ISimpleResourceLoader
 {
-	std::string archiveName;
+	boost::filesystem::path archiveName;
 	std::string mountPoint;
 
-	std::unordered_map<ResourceID, unz_file_pos> files;
+	std::unordered_map<ResourceID, unz64_file_pos> files;
 
-	std::unordered_map<ResourceID, unz_file_pos> listFiles(const std::string & mountPoint, const std::string &archive);
+	std::unordered_map<ResourceID, unz64_file_pos> listFiles(const std::string & mountPoint, const boost::filesystem::path &archive);
 public:
-	CZipLoader(const std::string & mountPoint, const std::string & archive);
+	CZipLoader(const std::string & mountPoint, const boost::filesystem::path & archive);
 
 	/// Interface implementation
 	/// @see ISimpleResourceLoader
@@ -65,11 +65,11 @@ public:
 namespace ZipArchive
 {
 	/// List all files present in archive
-	std::vector<std::string> DLL_LINKAGE listFiles(std::string filename);
+	std::vector<std::string> DLL_LINKAGE listFiles(boost::filesystem::path filename);
 
 	/// extracts all files from archive "from" into destination directory "where". Directory must exist
-	bool DLL_LINKAGE extract(std::string from, std::string where);
+	bool DLL_LINKAGE extract(boost::filesystem::path from, boost::filesystem::path where);
 
 	///same as above, but extracts only files mentioned in "what" list
-	bool DLL_LINKAGE extract(std::string from, std::string where, std::vector<std::string> what);
+	bool DLL_LINKAGE extract(boost::filesystem::path from, boost::filesystem::path where, std::vector<std::string> what);
 }

+ 156 - 0
lib/filesystem/FileStream.cpp

@@ -0,0 +1,156 @@
+#include "StdInc.h"
+#include "FileStream.h"
+
+#ifdef USE_SYSTEM_MINIZIP
+#include <minizip/unzip.h>
+#else
+#include "../minizip/unzip.h"
+#endif
+
+#include <cstdio>
+
+
+#ifdef VCMI_WINDOWS
+	#ifndef _CRT_SECURE_NO_WARNINGS
+		#define _CRT_SECURE_NO_WARNINGS
+	#endif
+	#include <cwchar>
+	#define CHAR_LITERAL(s) L##s
+	using CharType = wchar_t;
+#else
+	#define CHAR_LITERAL(s) s
+	using CharType = char;
+#endif
+
+inline FILE* do_open(const CharType* name, const CharType* mode)
+{
+	#ifdef VCMI_WINDOWS
+		return _wfopen(name, mode);
+	#else
+		return std::fopen(name, mode);
+	#endif
+}
+
+#define GETFILE static_cast<std::FILE*>(filePtr)
+
+voidpf ZCALLBACK MinizipOpenFunc(voidpf opaque, const void* filename, int mode)
+{
+    const CharType* mode_fopen = [mode]() -> const CharType*
+    {
+		if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER) == ZLIB_FILEFUNC_MODE_READ)
+			return CHAR_LITERAL("rb");
+		else if (mode & ZLIB_FILEFUNC_MODE_EXISTING)
+			return CHAR_LITERAL("r+b");
+		else if (mode & ZLIB_FILEFUNC_MODE_CREATE)
+			return CHAR_LITERAL("wb");
+		return nullptr;
+    }();
+
+    if (filename != nullptr && mode_fopen != nullptr)
+        return do_open(static_cast<const CharType*>(filename), mode_fopen);
+	else
+		return nullptr;
+}
+
+zlib_filefunc64_def* FileStream::GetMinizipFilefunc()
+{
+	static zlib_filefunc64_def MinizipFilefunc;
+	static bool initialized = false;
+	if (!initialized) {
+		fill_fopen64_filefunc((&MinizipFilefunc));
+		MinizipFilefunc.zopen64_file = &MinizipOpenFunc;
+		initialized = true;
+	}
+	return &MinizipFilefunc;
+}
+
+template class boost::iostreams::stream<FileBuf>;
+
+/*static*/
+bool FileStream::CreateFile(const boost::filesystem::path& filename)
+{
+	FILE* f = do_open(filename.c_str(), CHAR_LITERAL("wb"));
+	bool result = (f != nullptr);
+	fclose(f);
+	return result;
+}
+
+FileBuf::FileBuf(const boost::filesystem::path& filename, std::ios_base::openmode mode)
+{
+	auto openmode = [mode]() -> std::basic_string<CharType>
+	{
+		using namespace std;
+		switch (mode & (~ios_base::ate & ~ios_base::binary))
+		{
+		case (ios_base::in):
+			return CHAR_LITERAL("r");
+		case (ios_base::out):
+		case (ios_base::out | ios_base::trunc):
+			return CHAR_LITERAL("w");
+		case (ios_base::app):
+		case (ios_base::out | ios_base::app):
+			return CHAR_LITERAL("a");
+		case (ios_base::out | ios_base::in):
+			return CHAR_LITERAL("r+");
+		case (ios_base::out | ios_base::in | ios_base::trunc):
+			return CHAR_LITERAL("w+");
+		case (ios_base::out | ios_base::in | ios_base::app):
+		case (ios_base::in | ios_base::app):
+			return CHAR_LITERAL("a+");
+		default:
+			throw std::ios_base::failure("invalid open mode");
+		}
+	}();
+
+	if (mode & std::ios_base::binary)
+		openmode += CHAR_LITERAL('b');
+
+	filePtr = do_open(filename.c_str(), openmode.c_str());
+
+	if (filePtr == nullptr)
+		throw std::ios_base::failure("could not open file");
+
+	if (mode & std::ios_base::ate) {
+		if (std::fseek(GETFILE, 0, SEEK_END)) {
+			fclose(GETFILE);
+			throw std::ios_base::failure("could not open file");
+		}
+	}
+}
+
+void FileBuf::close()
+{
+    std::fclose(GETFILE);
+}
+
+std::streamsize FileBuf::read(char* s, std::streamsize n)
+{
+	return static_cast<std::streamsize>(std::fread(s, 1, n, GETFILE));
+}
+
+std::streamsize FileBuf::write(const char* s, std::streamsize n)
+{
+	return static_cast<std::streamsize>(std::fwrite(s, 1, n, GETFILE));
+}
+
+std::streamoff FileBuf::seek(std::streamoff off, std::ios_base::seekdir way)
+{
+	const auto src = [way]() -> int
+	{
+		switch(way)
+		{
+		case std::ios_base::beg:
+			return SEEK_SET;
+		case std::ios_base::cur:
+			return SEEK_CUR;
+		case std::ios_base::end:
+			return SEEK_END;
+		default:
+			throw std::ios_base::failure("bad seek direction");
+		}
+	}();
+	if(std::fseek(GETFILE, off, src))
+		throw std::ios_base::failure("bad seek offset");
+
+	return static_cast<std::streamsize>(std::ftell(GETFILE));
+}

+ 53 - 0
lib/filesystem/FileStream.h

@@ -0,0 +1,53 @@
+#pragma once
+
+/*
+ * FileStream.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
+ *
+ */
+
+#include <boost/iostreams/categories.hpp>
+#include <boost/iostreams/stream.hpp>
+
+class DLL_LINKAGE FileBuf
+{
+public:
+	typedef char char_type;
+	typedef struct category_ :
+		boost::iostreams::seekable_device_tag,
+		boost::iostreams::closable_tag
+		{} category;
+
+	FileBuf(const boost::filesystem::path& filename, std::ios_base::openmode mode);
+
+	std::streamsize read(char* s, std::streamsize n);
+	std::streamsize write(const char* s, std::streamsize n);
+	std::streamoff  seek(std::streamoff off, std::ios_base::seekdir way);
+
+	void close();
+private:
+	void* filePtr;
+};
+
+struct zlib_filefunc64_def_s;
+typedef zlib_filefunc64_def_s zlib_filefunc64_def;
+
+#ifdef VCMI_DLL
+extern template class DLL_LINKAGE boost::iostreams::stream<FileBuf>;
+#endif
+
+class DLL_LINKAGE FileStream : public boost::iostreams::stream<FileBuf>
+{
+public:
+	FileStream() = default;
+	explicit FileStream(const boost::filesystem::path& p, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out)
+		: boost::iostreams::stream<FileBuf>(p, mode) {}
+
+	static bool CreateFile(const boost::filesystem::path& filename);
+
+	static zlib_filefunc64_def* GetMinizipFilefunc();
+};

+ 2 - 2
lib/filesystem/ISimpleResourceLoader.h

@@ -48,9 +48,9 @@ public:
 	 *
 	 * @return path or empty optional if file can't be accessed independently (e.g. file in archive)
 	 */
-	virtual boost::optional<std::string> getResourceName(const ResourceID & resourceName) const
+	virtual boost::optional<boost::filesystem::path> getResourceName(const ResourceID & resourceName) const
 	{
-		return boost::optional<std::string>();
+		return boost::optional<boost::filesystem::path>();
 	}
 
 	/**

+ 4 - 3
lib/logging/CLogger.h

@@ -12,6 +12,7 @@
 #pragma once
 
 #include "../CConsoleHandler.h"
+#include "../filesystem/FileStream.h"
 
 class CLogger;
 struct LogRecord;
@@ -147,7 +148,7 @@ private:
 
 /// Macros for tracing the control flow of the application conveniently. If the LOG_TRACE macro is used it should be
 /// the first statement in the function. Logging traces via this macro have almost no impact when the trace is disabled.
-/// 
+///
 #define RAII_TRACE(logger, onEntry, onLeave)			\
 	std::unique_ptr<CTraceLogger> ctl00;						\
 	if(logger->isTraceEnabled())						\
@@ -217,7 +218,7 @@ public:
 	CLogFormatter(CLogFormatter && move);
 
 	CLogFormatter(const std::string & pattern);
-	
+
 	CLogFormatter & operator=(const CLogFormatter & copy);
 	CLogFormatter & operator=(CLogFormatter && move);
 
@@ -302,7 +303,7 @@ public:
 	void write(const LogRecord & record) override;
 
 private:
-	boost::filesystem::ofstream file;
+	FileStream file;
 	CLogFormatter formatter;
 	mutable boost::mutex mx;
 };

+ 10 - 4
server/VCMI_server.cbp

@@ -3,13 +3,14 @@
 	<FileVersion major="1" minor="6" />
 	<Project>
 		<Option title="VCMI_server" />
-		<Option pch_mode="2" />
+		<Option pch_mode="0" />
 		<Option compiler="gcc" />
 		<Build>
 			<Target title="Debug-win32">
 				<Option platforms="Windows;" />
 				<Option output="../VCMI_server" prefix_auto="1" extension_auto="1" />
-				<Option object_output="../obj/Debug/Server" />
+				<Option working_dir="../" />
+				<Option object_output="../obj/Server/Debug/x86" />
 				<Option type="1" />
 				<Option compiler="gcc" />
 				<Option use_console_runner="0" />
@@ -25,7 +26,8 @@
 			<Target title="Release-win32">
 				<Option platforms="Windows;" />
 				<Option output="../VCMI_server" prefix_auto="1" extension_auto="1" />
-				<Option object_output="../obj/Release/Server" />
+				<Option working_dir="../" />
+				<Option object_output="../obj/Server/Release/x86" />
 				<Option type="1" />
 				<Option compiler="gcc" />
 				<Option use_console_runner="0" />
@@ -42,7 +44,8 @@
 			<Target title="Debug-win64">
 				<Option platforms="Windows;" />
 				<Option output="../VCMI_server" prefix_auto="1" extension_auto="1" />
-				<Option object_output="../obj/Debug/Server" />
+				<Option working_dir="../" />
+				<Option object_output="../obj/Server/Debug/x86" />
 				<Option type="1" />
 				<Option compiler="gnu_gcc_compiler_x64" />
 				<Option use_console_runner="0" />
@@ -59,6 +62,7 @@
 		<Compiler>
 			<Add option="-Wextra" />
 			<Add option="-Wall" />
+			<Add option="-std=gnu++11" />
 			<Add option="-fexceptions" />
 			<Add option="-Wpointer-arith" />
 			<Add option="-Wno-switch" />
@@ -67,6 +71,8 @@
 			<Add option="-Wno-overloaded-virtual" />
 			<Add option="-D_WIN32_WINNT=0x0501" />
 			<Add option="-DBOOST_THREAD_USE_LIB" />
+			<Add option="-DBOOST_SYSTEM_NO_DEPRECATED" />
+			<Add option="-D_WIN32" />
 			<Add directory="$(#boost.include)" />
 			<Add directory="../include" />
 			<Add directory="$(#sdl2.include)" />