Selaa lähdekoodia

Merge remote-tracking branch 'remotes/origin/develop' into feature/VCMIMapFormat1

Conflicts:
	lib/CMakeLists.txt
	lib/VCMI_lib.cbp
	lib/filesystem/CFileInputStream.cpp
	lib/filesystem/CZipLoader.cpp
	lib/rmg/CRmgTemplateZone.cpp
	vcmi.workspace
AlexVinS 9 vuotta sitten
vanhempi
sitoutus
a00dbd3dd1

+ 0 - 1
client/CBitmapHandler.cpp

@@ -1,7 +1,6 @@
 #include "StdInc.h"
 
 #include "../lib/filesystem/Filesystem.h"
-#include "../lib/filesystem/CFileInfo.h"
 #include "SDL.h"
 #include "SDL_image.h"
 #include "CBitmapHandler.h"

+ 1 - 0
client/CMakeLists.txt

@@ -57,6 +57,7 @@ set(client_SRCS
 		Graphics.cpp
 		mapHandler.cpp
 		NetPacksClient.cpp
+		SDLRWwrapper.cpp
 )
 
 set(client_HEADERS

+ 9 - 12
client/CMusicHandler.cpp

@@ -3,6 +3,7 @@
 
 #include "CMusicHandler.h"
 #include "CGameInfo.h"
+#include "SDLRWwrapper.h"
 #include "../lib/CCreatureHandler.h"
 #include "../lib/spells/CSpellHandler.h"
 #include "../lib/JsonNode.h"
@@ -86,7 +87,7 @@ CSoundHandler::CSoundHandler():
 	listener(std::bind(&CSoundHandler::onVolumeChange, this, _1));
 
 	// Vectors for helper(s)
-	pickupSounds = 
+	pickupSounds =
 	{
 		soundBase::pickup01, soundBase::pickup02, soundBase::pickup03,
 		soundBase::pickup04, soundBase::pickup05, soundBase::pickup06, soundBase::pickup07
@@ -303,7 +304,7 @@ void CMusicHandler::release()
 
 void CMusicHandler::playMusic(std::string musicURI, bool loop)
 {
-	if (current && current->isTrack( musicURI))
+	if (current && current->isTrack(musicURI))
 		return;
 
 	queueNext(this, "", musicURI, loop);
@@ -342,7 +343,7 @@ void CMusicHandler::playMusicFromSet(std::string whichSet, int entryID, bool loo
 		return;
 	}
 
-	if (current && current->isTrack( selectedEntry->second))
+	if (current && current->isTrack(selectedEntry->second))
 		return;
 
 	// in this mode - play specific track from set
@@ -421,12 +422,11 @@ void CMusicHandler::musicFinishedCallback(void)
 MusicEntry::MusicEntry(CMusicHandler *owner, std::string setName, std::string musicURI, bool looped):
 	owner(owner),
 	music(nullptr),
-    musicFile(nullptr),
 	loop(looped ? -1 : 1),
-    setName(setName)
+    setName(std::move(setName))
 {
 	if (!musicURI.empty())
-		load(musicURI);
+		load(std::move(musicURI));
 }
 MusicEntry::~MusicEntry()
 {
@@ -448,15 +448,12 @@ void MusicEntry::load(std::string musicURI)
 
 	logGlobal->traceStream()<<"Loading music file "<<musicURI;
 
-	data = CResourceHandler::get()->load(ResourceID(musicURI, EResType::MUSIC))->readAll();
-	musicFile = SDL_RWFromConstMem(data.first.get(), data.second);
-	
-	music = Mix_LoadMUS_RW(musicFile, SDL_FALSE);
+	auto musicFile = MakeSDLRWops(CResourceHandler::get()->load(ResourceID(std::move(musicURI), EResType::MUSIC)));
+
+	music = Mix_LoadMUS_RW(musicFile, SDL_TRUE);
 
 	if(!music)
 	{
-		SDL_FreeRW(musicFile);
-		musicFile = nullptr;
 		logGlobal->warnStream() << "Warning: Cannot open " << currentName << ": " << Mix_GetError();
 		return;
 	}

+ 1 - 3
client/CMusicHandler.h

@@ -80,10 +80,8 @@ class CMusicHandler;
 //Class for handling one music file
 class MusicEntry
 {
-	std::pair<std::unique_ptr<ui8[]>, size_t> data;
 	CMusicHandler *owner;
 	Mix_Music *music;
-	SDL_RWops *musicFile;
 
 	int loop; // -1 = indefinite
 	//if not null - set from which music will be randomly selected
@@ -116,7 +114,7 @@ private:
 
 	std::unique_ptr<MusicEntry> current;
 	std::unique_ptr<MusicEntry> next;
-	
+
 	void queueNext(CMusicHandler *owner, std::string setName, std::string musicURI, bool looped);
 	void queueNext(std::unique_ptr<MusicEntry> queued);
 

+ 0 - 1
client/CPreGame.cpp

@@ -2,7 +2,6 @@
 #include "CPreGame.h"
 
 #include "../lib/filesystem/Filesystem.h"
-#include "../lib/filesystem/CFileInfo.h"
 #include "../lib/filesystem/CCompressedStream.h"
 
 #include "../lib/CStopWatch.h"

+ 6 - 6
client/NetPacksClient.cpp

@@ -2,7 +2,7 @@
 #include "../lib/NetPacks.h"
 
 #include "../lib/filesystem/Filesystem.h"
-#include "../lib/filesystem/CFileInfo.h"
+#include "../lib/filesystem/FileInfo.h"
 #include "../CCallback.h"
 #include "Client.h"
 #include "CPlayerInterface.h"
@@ -636,8 +636,8 @@ void BattleSetActiveStack::applyCl( CClient *cl )
 	PlayerColor playerToCall; //player that will move activated stack
 	if( activated->hasBonusOfType(Bonus::HYPNOTIZED) )
 	{
-		playerToCall = ( GS(cl)->curB->sides[0].color == activated->owner 
-			? GS(cl)->curB->sides[1].color 
+		playerToCall = ( GS(cl)->curB->sides[0].color == activated->owner
+			? GS(cl)->curB->sides[1].color
 			: GS(cl)->curB->sides[0].color );
 	}
 	else
@@ -803,12 +803,12 @@ void YourTurn::applyCl( CClient *cl )
 
 void SaveGame::applyCl(CClient *cl)
 {
-	CFileInfo info(fname);
-	CResourceHandler::get("local")->createResource(info.getStem() + ".vcgm1");
+	const auto stem = FileInfo::GetPathStem(fname);
+	CResourceHandler::get("local")->createResource(stem.to_string() + ".vcgm1");
 
 	try
 	{
-		CSaveFile save(*CResourceHandler::get()->getResourceName(ResourceID(info.getStem(), EResType::CLIENT_SAVEGAME)));
+		CSaveFile save(*CResourceHandler::get()->getResourceName(ResourceID(stem.to_string(), EResType::CLIENT_SAVEGAME)));
 		cl->saveCommonState(save);
 		save << *cl;
 	}

+ 95 - 0
client/SDLRWwrapper.cpp

@@ -0,0 +1,95 @@
+/*
+ * SDLRWwrapper.cpp, part of VCMI engine
+ *
+ * Authors: listed in file AUTHORS in main folder
+ *
+ * License: GNU General Public License v2.0 or later
+ * Full text of license available in license.txt file, in main folder
+ *
+ */
+
+#include "StdInc.h"
+#include "SDLRWwrapper.h"
+#include "../lib/filesystem/CInputStream.h"
+#include <SDL_rwops.h>
+
+static inline CInputStream* get_stream(SDL_RWops* context)
+{
+	return static_cast<CInputStream*>(context->hidden.unknown.data1);
+}
+
+static Sint64 impl_size(SDL_RWops* context)
+{
+    return get_stream(context)->getSize();
+}
+
+static Sint64 impl_seek(SDL_RWops* context, Sint64 offset, int whence)
+{
+	auto stream = get_stream(context);
+	switch (whence)
+	{
+	case RW_SEEK_SET:
+		return stream->seek(offset);
+		break;
+	case RW_SEEK_CUR:
+		return stream->seek(stream->tell() + offset);
+		break;
+	case RW_SEEK_END:
+		return stream->seek(stream->getSize() + offset);
+		break;
+	default:
+		return -1;
+	}
+
+}
+
+static std::size_t impl_read(SDL_RWops* context, void *ptr, size_t size, size_t maxnum)
+{
+    auto stream = get_stream(context);
+    auto oldpos = stream->tell();
+
+    auto count = stream->read(static_cast<ui8*>(ptr), size*maxnum);
+
+	if (count != 0 && count != size*maxnum)
+	{
+		// if not a whole amount of objects of size has been read, we need to seek
+		stream->seek(oldpos + size * (count / size));
+	}
+
+    return count / size;
+}
+
+static std::size_t impl_write(SDL_RWops* context, const void *ptr, size_t size, size_t num)
+{
+	// writing is not supported
+    return 0;
+}
+
+static int impl_close(SDL_RWops* context)
+{
+	if (context == nullptr)
+		return 0;
+
+    delete get_stream(context);
+    SDL_FreeRW(context);
+    return 0;
+}
+
+
+SDL_RWops* MakeSDLRWops(std::unique_ptr<CInputStream> in)
+{
+	SDL_RWops* result = SDL_AllocRW();
+	if (!result)
+		return nullptr;
+
+	result->size  = &impl_size;
+	result->seek  = &impl_seek;
+	result->read  = &impl_read;
+	result->write = &impl_write;
+	result->close = &impl_close;
+
+	result->type = SDL_RWOPS_UNKNOWN;
+	result->hidden.unknown.data1 = in.release();
+
+	return result;
+}

+ 16 - 0
client/SDLRWwrapper.h

@@ -0,0 +1,16 @@
+#pragma once
+
+/*
+ * SDLRWwrapper.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
+ *
+ */
+
+struct SDL_RWops;
+class CInputStream;
+
+SDL_RWops* MakeSDLRWops(std::unique_ptr<CInputStream> in);

+ 3 - 2
client/VCMI_client.cbp

@@ -70,12 +70,11 @@
 			<Add option="-Wno-unused-parameter" />
 			<Add option="-Wno-overloaded-virtual" />
 			<Add option="-fpermissive" />
+			<Add option="-isystem $(#boost.include)" />
 			<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" />
 			<Add directory="$(#ffmpeg.include)" />
 			<Add directory="$(#sdl2.include)" />
@@ -126,6 +125,8 @@
 		<Unit filename="Graphics.h" />
 		<Unit filename="NetPacksClient.cpp" />
 		<Unit filename="SDLMain.h" />
+		<Unit filename="SDLRWwrapper.cpp" />
+		<Unit filename="SDLRWwrapper.h" />
 		<Unit filename="StdInc.h">
 			<Option weight="0" />
 		</Unit>

+ 50 - 59
client/gui/CAnimation.cpp

@@ -51,11 +51,11 @@ class CompImageLoader
 	ui8 *position;
 	ui8 *entry;
 	ui32 currentLine;
-	
+
 	inline ui8 typeOf(ui8 color);
 	inline void NewEntry(ui8 color, size_t size);
 	inline void NewEntry(const ui8 * &data, size_t size);
-	
+
 public:
 	//load size raw pixels from data
 	inline void Load(size_t size, const ui8 * data);
@@ -75,29 +75,26 @@ class CFileCache
 	static const int cacheSize = 50; //Max number of cached files
 	struct FileData
 	{
-		ResourceID name;
-		size_t size;
-		ui8 * data;
+		ResourceID             name;
+		size_t                 size;
+		std::unique_ptr<ui8[]> data;
 
-		ui8 * getCopy()
+		std::unique_ptr<ui8[]> getCopy()
 		{
-			auto   ret = new ui8[size];
-			std::copy(data, data + size, ret);
+			auto ret = std::unique_ptr<ui8[]>(new ui8[size]);
+			std::copy(data.get(), data.get() + size, ret.get());
 			return ret;
 		}
-		FileData():
-		    size(0),
-		    data(nullptr)
+		FileData(ResourceID name_, size_t size_, std::unique_ptr<ui8[]> data_):
+			name{std::move(name_)},
+			size{size_},
+			data{std::move(data_)}
 		{}
-		~FileData()
-		{
-			delete [] data;
-		}
 	};
 
-	std::list<FileData> cache;
+	std::deque<FileData> cache;
 public:
-	ui8 * getCachedFile(ResourceID && rid)
+	std::unique_ptr<ui8[]> getCachedFile(ResourceID rid)
 	{
 		for(auto & file : cache)
 		{
@@ -107,12 +104,10 @@ public:
 		// Still here? Cache miss
 		if (cache.size() > cacheSize)
 			cache.pop_front();
-		cache.push_back(FileData());
 
 		auto data =  CResourceHandler::get()->load(rid)->readAll();
-		cache.back().name = ResourceID(rid);
-		cache.back().size = data.second;
-		cache.back().data = data.first.release();
+
+		cache.emplace_back(std::move(rid), data.second, std::move(data.first));
 
 		return cache.back().getCopy();
 	}
@@ -142,15 +137,15 @@ CDefFile::CDefFile(std::string Name):
 	};
 	data = animationCache.getCachedFile(ResourceID(std::string("SPRITES/") + Name, EResType::ANIMATION));
 
-	palette = new SDL_Color[256];
+	palette = std::unique_ptr<SDL_Color[]>(new SDL_Color[256]);
 	int it = 0;
 
-	ui32 type = read_le_u32(data + it);
+	ui32 type = read_le_u32(data.get() + it);
 	it+=4;
 	//int width  = read_le_u32(data + it); it+=4;//not used
 	//int height = read_le_u32(data + it); it+=4;
 	it+=8;
-	ui32 totalBlocks = read_le_u32(data + it);
+	ui32 totalBlocks = read_le_u32(data.get() + it);
 	it+=4;
 
 	for (ui32 i= 0; i<256; i++)
@@ -161,15 +156,15 @@ CDefFile::CDefFile(std::string Name):
 		palette[i].a = SDL_ALPHA_OPAQUE;
 	}
 	if (type == 71 || type == 64)//Buttons/buildings don't have shadows\semi-transparency
-		memset(palette, 0, sizeof(SDL_Color)*2);
+		memset(palette.get(), 0, sizeof(SDL_Color)*2);
 	else
-		memcpy(palette, H3Palette, sizeof(SDL_Color)*8);//initialize shadow\selection colors
+		memcpy(palette.get(), H3Palette, sizeof(SDL_Color)*8);//initialize shadow\selection colors
 
 	for (ui32 i=0; i<totalBlocks; i++)
 	{
-		size_t blockID = read_le_u32(data + it);
+		size_t blockID = read_le_u32(data.get() + it);
 		it+=4;
-		size_t totalEntries = read_le_u32(data + it);
+		size_t totalEntries = read_le_u32(data.get() + it);
 		it+=12;
 		//8 unknown bytes - skipping
 
@@ -178,7 +173,7 @@ CDefFile::CDefFile(std::string Name):
 
 		for (ui32 j=0; j<totalEntries; j++)
 		{
-			size_t currOffset = read_le_u32(data + it);
+			size_t currOffset = read_le_u32(data.get() + it);
 			offset[blockID].push_back(currOffset);
 			it += 4;
 		}
@@ -192,7 +187,7 @@ void CDefFile::loadFrame(size_t frame, size_t group, ImageLoader &loader) const
 	it = offset.find(group);
 	assert (it != offset.end());
 
-	const ui8 * FDef = data+it->second[frame];
+	const ui8 * FDef = data.get()+it->second[frame];
 
 	const SSpriteDef sd = * reinterpret_cast<const SSpriteDef *>(FDef);
 	SSpriteDef sprite;
@@ -210,7 +205,7 @@ void CDefFile::loadFrame(size_t frame, size_t group, ImageLoader &loader) const
 
 	loader.init(Point(sprite.width, sprite.height),
 	            Point(sprite.leftMargin, sprite.topMargin),
-	            Point(sprite.fullWidth, sprite.fullHeight), palette);
+	            Point(sprite.fullWidth, sprite.fullHeight), palette.get());
 
 	switch (sprite.format)
 	{
@@ -321,11 +316,7 @@ void CDefFile::loadFrame(size_t frame, size_t group, ImageLoader &loader) const
 	}
 };
 
-CDefFile::~CDefFile()
-{
-	delete[] data;
-	delete[] palette;
-}
+CDefFile::~CDefFile() = default;
 
 const std::map<size_t, size_t > CDefFile::getEntries() const
 {
@@ -355,10 +346,10 @@ void SDLImageLoader::init(Point SpriteSize, Point Margins, Point FullSize, SDL_C
 	image->fullSize = FullSize;
 
 	//Prepare surface
-	SDL_Palette * p = SDL_AllocPalette(256);	
+	SDL_Palette * p = SDL_AllocPalette(256);
 	SDL_SetPaletteColors(p, pal, 0, 256);
 	SDL_SetSurfacePalette(image->surf, p);
-	SDL_FreePalette(p);	
+	SDL_FreePalette(p);
 
 	SDL_LockSurface(image->surf);
 	lineStart = position = (ui8*)image->surf->pixels;
@@ -396,14 +387,14 @@ SDLImageLoader::~SDLImageLoader()
 }
 
 ////////////////////////////////////////////////////////////////////////////////
- 
+
 CompImageLoader::CompImageLoader(CompImage * Img):
 	image(Img),
 	position(nullptr),
 	entry(nullptr),
 	currentLine(0)
 {
-	
+
 }
 
 void CompImageLoader::init(Point SpriteSize, Point Margins, Point FullSize, SDL_Color *pal)
@@ -451,7 +442,7 @@ inline ui8 CompImageLoader::typeOf(ui8 color)
 
 	if (image->palette[color].a != 255)
 		return 1;
-		
+
 	return 2;
 }
 
@@ -489,7 +480,7 @@ inline void CompImageLoader::Load(size_t size, const ui8 * data)
 		ui8 type = typeOf(color);
 		ui8 color2;
 		ui8 type2;
-		
+
 		if (size > 1)
 		{
 			do
@@ -632,7 +623,7 @@ SDLImage::SDLImage(std::string filename, bool compressed):
 		{
 			CSDL_Ext::setColorKey(temp,temp->format->palette->colors[0]);
 		}
-		SDL_SetSurfaceRLE(temp, SDL_RLEACCEL);		
+		SDL_SetSurfaceRLE(temp, SDL_RLEACCEL);
 
 		// convert surface to enable RLE
 		surf = SDL_ConvertSurface(temp, temp->format, temp->flags);
@@ -680,7 +671,7 @@ CompImage::CompImage(const CDefFile *data, size_t frame, size_t group):
 	surf(nullptr),
 	line(nullptr),
 	palette(nullptr)
-	
+
 {
 	CompImageLoader loader(this);
 	data->loadFrame(frame, group, loader);
@@ -738,7 +729,7 @@ void CompImage::draw(SDL_Surface *where, int posX, int posY, Rect *src, ui8 alph
 
 		currX = 0;
 		ui8 bpp = where->format->BytesPerPixel;
-		
+
 		//Calculate position for blitting: pixels + Y + X
 		ui8* blitPos = (ui8*) where->pixels;
 		if (rotation & 4)
@@ -769,7 +760,7 @@ void CompImage::draw(SDL_Surface *where, int posX, int posY, Rect *src, ui8 alph
 void CompImage::BlitBlockWithBpp(ui8 bpp, ui8 type, ui8 size, ui8 *&data, ui8 *&dest, ui8 alpha, bool rotated) const
 {
 	assert(bpp>1 && bpp<5);
-	
+
 	if (rotated)
 		switch (bpp)
 		{
@@ -817,7 +808,7 @@ void CompImage::BlitBlock(ui8 type, ui8 size, ui8 *&data, ui8 *&dest, ui8 alpha)
 			//Put row of RGBA data
 			for (size_t i=0; i<size; i++)
 				ColorPutter<bpp, 1>::PutColorAlpha(dest, palette[*(data++)]);
-			
+
 		}
 	}
 	//RLE-d sequence
@@ -831,7 +822,7 @@ void CompImage::BlitBlock(ui8 type, ui8 size, ui8 *&data, ui8 *&dest, ui8 alpha)
 				ColorPutter<bpp, 1>::PutColorAlpha(dest, col);
 			return;
 		}
-		
+
 		switch (palette[type].a)
 		{
 			case 0:
@@ -958,7 +949,7 @@ bool CAnimation::loadFrame(CDefFile * file, size_t frame, size_t group)
 	else //load from separate file
 	{
 		std::string filename = source[group][frame].Struct().find("file")->second.String();
-	
+
 		IImage * img = getFromExtraDef(filename);
 		if (!img)
 			img = new SDLImage(filename, compressed);
@@ -1183,7 +1174,7 @@ void CAnimation::getAnimInfo()
     logGlobal->errorStream()<<"Animation stats: Loaded "<<loadedAnims.size()<<" total";
 	for (auto anim : loadedAnims)
 	{
-		
+
         logGlobal->errorStream()<<"Name: "<<anim->name<<" Groups: "<<anim->images.size();
 		if (!anim->images.empty())
             logGlobal->errorStream()<<", "<<anim->images.begin()->second.size()<<" image loaded in group "<< anim->images.begin()->first;
@@ -1202,12 +1193,12 @@ void CFadeAnimation::update()
 {
 	if (!fading)
 		return;
-	
+
 	if (fadingMode == EMode::OUT)
 		fadingCounter -= delta;
 	else
 		fadingCounter += delta;
-		
+
 	if (isFinished())
 	{
 		fading = false;
@@ -1236,7 +1227,7 @@ CFadeAnimation::CFadeAnimation()
 CFadeAnimation::~CFadeAnimation()
 {
 	if (fadingSurface && shouldFreeSurface)
-		SDL_FreeSurface(fadingSurface);		
+		SDL_FreeSurface(fadingSurface);
 }
 
 void CFadeAnimation::init(EMode mode, SDL_Surface * sourceSurface, bool freeSurfaceAtEnd /* = false */, float animDelta /* = DEFAULT_DELTA */)
@@ -1247,17 +1238,17 @@ void CFadeAnimation::init(EMode mode, SDL_Surface * sourceSurface, bool freeSurf
 		// (alternatively, we could just return here to ignore the new fade request until this one finished (but we'd need to free the passed bitmap to avoid leaks))
 		logGlobal->warnStream() << "Tried to init fading animation that is already running.";
 		if (fadingSurface && shouldFreeSurface)
-			SDL_FreeSurface(fadingSurface); 
-	}		
+			SDL_FreeSurface(fadingSurface);
+	}
 	if (animDelta <= 0.0f)
 	{
 		logGlobal->warnStream() << "Fade anim: delta should be positive; " << animDelta << " given.";
 		animDelta = DEFAULT_DELTA;
 	}
-	
+
 	if (sourceSurface)
 		fadingSurface = sourceSurface;
-	
+
 	delta = animDelta;
 	fadingMode = mode;
 	fadingCounter = initialCounter();
@@ -1266,13 +1257,13 @@ void CFadeAnimation::init(EMode mode, SDL_Surface * sourceSurface, bool freeSurf
 }
 
 void CFadeAnimation::draw(SDL_Surface * targetSurface, const SDL_Rect * sourceRect, SDL_Rect * destRect)
-{	
+{
 	if (!fading || !fadingSurface || fadingMode == EMode::NONE)
 	{
 		fading = false;
 		return;
 	}
-	
+
 	CSDL_Ext::setAlpha(fadingSurface, fadingCounter * 255);
 	SDL_BlitSurface(fadingSurface, const_cast<SDL_Rect *>(sourceRect), targetSurface, destRect); //FIXME
 	CSDL_Ext::setAlpha(fadingSurface, 255);

+ 3 - 3
client/gui/CAnimation.h

@@ -39,8 +39,8 @@ private:
 	//offset[group][frame] - offset of frame data in file
 	std::map<size_t, std::vector <size_t> > offset;
 
-	ui8 * data;
-	SDL_Color * palette;
+	std::unique_ptr<ui8[]>       data;
+	std::unique_ptr<SDL_Color[]> palette;
 
 public:
 	CDefFile(std::string Name);
@@ -236,7 +236,7 @@ private:
 	bool fading;
 	float fadingCounter;
 	bool shouldFreeSurface;
-	
+
 	float initialCounter() const;
 	bool isFinished() const;
 public:

+ 1 - 1
config/creatures/neutral.json

@@ -480,7 +480,7 @@
 			"sandWalker" :
 			{
 				"type" : "NO_TERRAIN_PENALTY",
-				"subtype" : 1,
+				"subtype" : "terrain.sand",
 				"propagator" : "HERO"
 			}
 		},

+ 38 - 28
config/spells/ability.json

@@ -1,10 +1,10 @@
 {
 	"stoneGaze" : {
 		"index" : 70,
-		"targetType": "NO_TARGET",		
+		"targetType": "NO_TARGET",
 		"animation":{
 			//need special animation
-		},		
+		},
 		"sounds": {
 			"cast": "PARALYZE"
 		},
@@ -26,8 +26,18 @@
 						"val" : 0,
 						"type" : "NO_RETALIATION",
 						"duration" : "UNITL_BEING_ATTACKED"
+					},
+					"defenceBoost" : {
+						"type" : "PRIMARY_SKILL",
+						"subtype" : "primSkill.defence",
+						"val" : 50,
+						"valueType" : "PERCENT_TO_ALL",
+						"duration" : [
+						    "UNITL_BEING_ATTACKED",
+						    "N_TURNS"
+						]
 					}
-				}				
+				}
 			}
 		},
 		"flags" : {
@@ -37,10 +47,10 @@
 	"poison" : {
 		"index" : 71,
 		"targetType": "NO_TARGET",
-		
+
 		"animation":{
 			"affect":["SP11_"]
-		},		
+		},
 		"sounds": {
 			"cast": "POISON"
 		},
@@ -61,7 +71,7 @@
 						"valueType" : "PERCENT_TO_ALL",
 						"duration" : "N_TURNS"
 					}
-				}			
+				}
 			}
 		},
 		"immunity" : {
@@ -75,10 +85,10 @@
 	"bind" : {
 		"index" : 72,
 		"targetType": "NO_TARGET",
-		
+
 		"animation":{
 			"affect":["SP02_"]
-		},		
+		},
 		"sounds": {
 			"cast": "BIND"
 		},
@@ -92,7 +102,7 @@
 						"duration" : "PERMANENT",
 						"addInfo" : -1
 					}
-				}			
+				}
 			}
 		},
 		"flags" : {
@@ -102,10 +112,10 @@
 	"disease" : {
 		"index" : 73,
 		"targetType": "NO_TARGET",
-		
+
 		"animation":{
 			"affect":["SP05_"]
-		},		
+		},
 		"sounds": {
 			"cast": "DISEASE"
 		},
@@ -126,7 +136,7 @@
 						"subtype" : "primSkill.defence",
 						"duration" : "N_TURNS"
 					}
-				}		
+				}
 			}
 		},
 		"immunity" : {
@@ -140,10 +150,10 @@
 	"paralyze" : {
 		"index" : 74,
 		"targetType": "NO_TARGET",
-		
+
 		"animation":{
 			//missing
-		},		
+		},
 		"sounds": {
 			"cast": "PARALYZE"
 		},
@@ -176,10 +186,10 @@
 	"age" : {
 		"index" : 75,
 		"targetType": "NO_TARGET",
-		
+
 		"animation":{
 			"affect":["SP01_"]
-		},		
+		},
 		"sounds": {
 			"cast": "AGE"
 		},
@@ -208,10 +218,10 @@
 	"deathCloud" : {
 		"index" : 76,
 		"targetType": "NO_TARGET",
-		
+
 		"animation":{
 			"hit":["SP04_"]
-		},		
+		},
 		"sounds": {
 			"cast": "DEATHCLD"
 		},
@@ -231,10 +241,10 @@
 	"thunderbolt" : {
 		"index" : 77,
 		"targetType": "NO_TARGET",
-		
+
 		"animation":{
 			"affect":[{"defName":"C03SPA0", "verticalPosition":"bottom"}, "C11SPA1"]
-		},		
+		},
 		"sounds": {
 			"cast": "LIGHTBLT"
 		},
@@ -252,10 +262,10 @@
 	"dispelHelpful" : {
 		"index" : 78,
 		"targetType": "NO_TARGET",
-		
+
 		"animation":{
 			"affect":["C05SPW"]
-		},		
+		},
 		"sounds": {
 			"cast": "DISPELL"
 		},
@@ -272,10 +282,10 @@
 	"deathStare" : {
 		"index" : 79,
 		"targetType": "NO_TARGET",
-		
+
 		"animation":{
 			"affect":["C07SPE0"]
-		},		
+		},
 		"sounds": {
 			"cast": "DEATHSTR"
 		},
@@ -295,10 +305,10 @@
 	"acidBreath" : {
 		"index" : 80,
 		"targetType": "NO_TARGET",
-		
+
 		"animation":{
 			//???
-		},		
+		},
 		"sounds": {
 			"cast": "ACID"
 		},
@@ -324,10 +334,10 @@
 	"acidBreathDamage" : {
 		"index" : 81,
 		"targetType": "NO_TARGET",
-		
+
 		"animation":{
 			"affect":["C17SPW0"]
-		},		
+		},
 		"sounds": {
 			"cast": "ACID"
 		},

+ 4 - 4
launcher/VCMI_launcher.cbp

@@ -9,17 +9,18 @@
 			<Target title="Debug Win32">
 				<Option output="../VCMI_launcher" prefix_auto="1" extension_auto="1" />
 				<Option working_dir="../" />
-				<Option object_output=".objs/debug" />
+				<Option object_output="../obj/Launcher/Debug" />
 				<Option type="0" />
 				<Option compiler="gcc" />
 				<Compiler>
 					<Add option="-g" />
+					<Add option="-Og" />
 				</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 object_output="../obj/Launcher/Release" />
 				<Option type="0" />
 				<Option compiler="gcc" />
 				<Compiler>
@@ -36,11 +37,10 @@
 			<Add option="-Wextra" />
 			<Add option="-Wall" />
 			<Add option="-std=gnu++11" />
+			<Add option="-isystem $(#boost.include)" />
 			<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" />

+ 4 - 0
lib/CHeroHandler.cpp

@@ -291,6 +291,10 @@ CHeroHandler::CHeroHandler()
 	}
 	loadObstacles();
 	loadTerrains();
+	for (int i = 0; i < GameConstants::TERRAIN_TYPES; ++i)
+	{
+		VLC->modh->identifiers.registerObject("core", "terrain", GameConstants::TERRAIN_NAMES[i], i);
+	}
 	loadBallistics();
 	loadExperience();
 }

+ 5 - 5
lib/CMakeLists.txt

@@ -11,17 +11,17 @@ set(lib_SRCS
 		filesystem/CCompressedStream.cpp
 		filesystem/CFilesystemLoader.cpp
 		filesystem/CArchiveLoader.cpp
-		filesystem/CFileInfo.cpp
-                filesystem/CMemoryBuffer.cpp
-                filesystem/CMemoryStream.cpp
+		filesystem/CMemoryBuffer.cpp
+		filesystem/CMemoryStream.cpp
 		filesystem/CBinaryReader.cpp
 		filesystem/CFileInputStream.cpp
 		filesystem/CZipLoader.cpp
-                filesystem/CZipSaver.cpp
+		filesystem/CZipSaver.cpp
+		filesystem/FileInfo.cpp
 		filesystem/Filesystem.cpp
 		filesystem/FileStream.cpp
 		filesystem/ResourceID.cpp
-                filesystem/MinizipExtensions.cpp
+		filesystem/MinizipExtensions.cpp
 
 		mapObjects/CArmedInstance.cpp
 		mapObjects/CBank.cpp

+ 11 - 11
lib/VCMIDirs.cpp

@@ -31,7 +31,7 @@ void IVCMIDirs::init()
 
 	#ifndef CSIDL_MYDOCUMENTS
 	#define CSIDL_MYDOCUMENTS CSIDL_PERSONAL
-	#endif    
+	#endif
 #endif // __MINGW32__
 
 #include <windows.h>
@@ -87,7 +87,7 @@ bool StartBatchCopyDataProgram(
 		"%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.
@@ -107,7 +107,7 @@ bool StartBatchCopyDataProgram(
 	return true;
 }
 
-class VCMIDirsWIN32 : public IVCMIDirs
+class VCMIDirsWIN32 final : public IVCMIDirs
 {
 	public:
 		boost::filesystem::path userDataPath() const override;
@@ -166,7 +166,7 @@ void VCMIDirsWIN32::init()
 		{
 			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;
@@ -195,7 +195,7 @@ void VCMIDirsWIN32::init()
 			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);
 
@@ -203,7 +203,7 @@ void VCMIDirsWIN32::init()
 		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.
@@ -247,7 +247,7 @@ void VCMIDirsWIN32::init()
 		// Start copying script and exit program.
 		if (StartBatchCopyDataProgram(from, to, executableName))
 			exit(ERROR_SUCCESS);
-		
+
 		// Everything failed :C
 		return false;
 	};
@@ -262,14 +262,14 @@ bfs::path VCMIDirsWIN32::userDataPath() const
 
 	if (SHGetSpecialFolderPathW(nullptr, profileDir, CSIDL_MYDOCUMENTS, FALSE) != FALSE)
 		return bfs::path(profileDir) / "My Games\\vcmi";
-	
+
 	return ".";
 }
 
 bfs::path VCMIDirsWIN32::oldUserDataPath() const
 {
 	wchar_t profileDir[MAX_PATH];
-	
+
 	if (SHGetSpecialFolderPathW(nullptr, profileDir, CSIDL_PROFILE, FALSE) == FALSE) // WinAPI way failed
 	{
 #if defined(_MSC_VER) && _MSC_VER >= 1700
@@ -284,7 +284,7 @@ bfs::path VCMIDirsWIN32::oldUserDataPath() const
 		}
 #else
 		const char* profileDirA;
-		if (profileDirA = std::getenv("userprofile")) // STL way succeed
+		if ((profileDirA = std::getenv("userprofile"))) // STL way succeed
 			return bfs::path(profileDirA) / "vcmi";
 #endif
 		else
@@ -365,7 +365,7 @@ std::string IVCMIDirsUNIX::genHelpString() const
 }
 
 #ifdef VCMI_APPLE
-class VCMIDirsOSX : public IVCMIDirsUNIX
+class VCMIDirsOSX final : public IVCMIDirsUNIX
 {
 	public:
 		boost::filesystem::path userDataPath() const override;

+ 7 - 11
lib/VCMI_lib.cbp

@@ -19,7 +19,6 @@
 				<Compiler>
 					<Add option="-g" />
 					<Add option="-Og" />
-					<Add directory="$(#zlib.include)" />
 				</Compiler>
 				<Linker>
 					<Add option="-lws2_32" />
@@ -33,9 +32,7 @@
 					<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)" />
 				</Linker>
 			</Target>
 			<Target title="Release-win32">
@@ -48,7 +45,6 @@
 				<Compiler>
 					<Add option="-fomit-frame-pointer" />
 					<Add option="-O2" />
-					<Add directory="$(#zlib.include)" />
 				</Compiler>
 				<Linker>
 					<Add option="-s" />
@@ -62,9 +58,7 @@
 					<Add option="-lboost_locale$(#boost.libsuffix)" />
 					<Add option="-lboost_date_time$(#boost.libsuffix)" />
 					<Add option="-liconv" />
-					<Add directory="$(#sdl2.lib)" />
 					<Add directory="$(#boost.lib32)" />
-					<Add directory="$(#zlib.lib)" />
 				</Linker>
 			</Target>
 			<Target title="Debug-win64">
@@ -110,18 +104,20 @@
 			<Add option="-Wno-unused-parameter" />
 			<Add option="-Wno-overloaded-virtual" />
 			<Add option="-Wno-unused-local-typedefs" />
+			<Add option="-isystem $(#boost.include)" />
 			<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" />
+			<Add directory="." />
 			<Add directory="$(#sdl2.include)" />
+			<Add directory="$(#zlib.include)" />
 		</Compiler>
 		<Linker>
 			<Add directory="../" />
+			<Add directory="$(#sdl2.lib)" />
+			<Add directory="$(#zlib.lib)" />
 		</Linker>
 		<Unit filename="AI_Base.h" />
 		<Unit filename="BattleAction.cpp" />
@@ -217,8 +213,6 @@
 		<Unit filename="filesystem/CBinaryReader.h" />
 		<Unit filename="filesystem/CCompressedStream.cpp" />
 		<Unit filename="filesystem/CCompressedStream.h" />
-		<Unit filename="filesystem/CFileInfo.cpp" />
-		<Unit filename="filesystem/CFileInfo.h" />
 		<Unit filename="filesystem/CFileInputStream.cpp" />
 		<Unit filename="filesystem/CFileInputStream.h" />
 		<Unit filename="filesystem/CFilesystemLoader.cpp" />
@@ -235,6 +229,8 @@
 		<Unit filename="filesystem/CZipLoader.h" />
 		<Unit filename="filesystem/CZipSaver.cpp" />
 		<Unit filename="filesystem/CZipSaver.h" />
+		<Unit filename="filesystem/FileInfo.cpp" />
+		<Unit filename="filesystem/FileInfo.h" />
 		<Unit filename="filesystem/FileStream.cpp" />
 		<Unit filename="filesystem/FileStream.h" />
 		<Unit filename="filesystem/Filesystem.cpp" />

+ 2 - 1
lib/filesystem/AdapterLoaders.cpp

@@ -8,7 +8,8 @@ CMappedFileLoader::CMappedFileLoader(const std::string & mountPoint, const JsonN
 {
 	for(auto entry : config.Struct())
 	{
-		fileList[ResourceID(mountPoint + entry.first)] = ResourceID(mountPoint + entry.second.String());
+		//fileList[ResourceID(mountPoint + entry.first)] = ResourceID(mountPoint + entry.second.String());
+		fileList.emplace(ResourceID(mountPoint + entry.first), ResourceID(mountPoint + entry.second.String()));
 	}
 }
 

+ 83 - 84
lib/filesystem/AdapterLoaders.h

@@ -1,87 +1,86 @@
-#pragma once
-
-/*
- * AdapterLoaders.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 "ISimpleResourceLoader.h"
-#include "ResourceID.h"
-
-class CFileInfo;
-class CInputStream;
-class JsonNode;
-
-/**
- * Class that implements file mapping (aka *nix symbolic links)
- * Uses json file as input, content is map:
- * "fileA.txt" : "fileB.txt"
- * Note that extension is necessary, but used only to determine type
- *
- * fileA - file which will be replaced
- * fileB - file which will be used as replacement
- */
-class DLL_LINKAGE CMappedFileLoader : public ISimpleResourceLoader
-{
-public:
-	/**
-	 * Ctor.
-	 *
-	 * @param config Specifies filesystem configuration
-	 */
-	explicit CMappedFileLoader(const std::string &mountPoint, const JsonNode & config);
-
-	/// Interface implementation
-	/// @see ISimpleResourceLoader
-	std::unique_ptr<CInputStream> load(const ResourceID & resourceName) const override;
-	bool existsResource(const ResourceID & resourceName) const override;
-	std::string getMountPoint() 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:
-	/** A list of files in this map
-	 * key = ResourceID for resource loader
-	 * value = ResourceID to which file this request will be redirected
-	*/
-	std::unordered_map<ResourceID, ResourceID> fileList;
-};
-
-class DLL_LINKAGE CFilesystemList : public ISimpleResourceLoader
-{
-	std::vector<std::unique_ptr<ISimpleResourceLoader> > loaders;
-
-	std::set<ISimpleResourceLoader *> writeableLoaders;
-
-	//FIXME: this is only compile fix, should be removed in the end
+#pragma once
+
+/*
+ * AdapterLoaders.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 "ISimpleResourceLoader.h"
+#include "ResourceID.h"
+
+class CInputStream;
+class JsonNode;
+
+/**
+ * Class that implements file mapping (aka *nix symbolic links)
+ * Uses json file as input, content is map:
+ * "fileA.txt" : "fileB.txt"
+ * Note that extension is necessary, but used only to determine type
+ *
+ * fileA - file which will be replaced
+ * fileB - file which will be used as replacement
+ */
+class DLL_LINKAGE CMappedFileLoader : public ISimpleResourceLoader
+{
+public:
+	/**
+	 * Ctor.
+	 *
+	 * @param config Specifies filesystem configuration
+	 */
+	explicit CMappedFileLoader(const std::string &mountPoint, const JsonNode & config);
+
+	/// Interface implementation
+	/// @see ISimpleResourceLoader
+	std::unique_ptr<CInputStream> load(const ResourceID & resourceName) const override;
+	bool existsResource(const ResourceID & resourceName) const override;
+	std::string getMountPoint() 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:
+	/** A list of files in this map
+	 * key = ResourceID for resource loader
+	 * value = ResourceID to which file this request will be redirected
+	*/
+	std::unordered_map<ResourceID, ResourceID> fileList;
+};
+
+class DLL_LINKAGE CFilesystemList : public ISimpleResourceLoader
+{
+	std::vector<std::unique_ptr<ISimpleResourceLoader> > loaders;
+
+	std::set<ISimpleResourceLoader *> writeableLoaders;
+
+	//FIXME: this is only compile fix, should be removed in the end
 	CFilesystemList(CFilesystemList &) = delete;
 	CFilesystemList &operator=(CFilesystemList &) = delete;
-
-public:
-	CFilesystemList();
-	~CFilesystemList();
-	/// Interface implementation
-	/// @see ISimpleResourceLoader
-	std::unique_ptr<CInputStream> load(const ResourceID & resourceName) const override;
-	bool existsResource(const ResourceID & resourceName) const override;
-	std::string getMountPoint() const override;
-	boost::optional<boost::filesystem::path> getResourceName(const ResourceID & resourceName) const override;
+
+public:
+	CFilesystemList();
+	~CFilesystemList();
+	/// Interface implementation
+	/// @see ISimpleResourceLoader
+	std::unique_ptr<CInputStream> load(const ResourceID & resourceName) const override;
+	bool existsResource(const ResourceID & resourceName) const override;
+	std::string getMountPoint() const override;
+	boost::optional<boost::filesystem::path> getResourceName(const ResourceID & resourceName) const override;
 	std::set<boost::filesystem::path> 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;
-	std::vector<const ISimpleResourceLoader *> getResourcesWithName(const ResourceID & resourceName) const override;
-
-	/**
-	 * Adds a resource loader to the loaders list
-	 * Passes loader ownership to this object
-	 *
-	 * @param loader The simple resource loader object to add
-	 * @param writeable - resource shall be treated as writeable
-	 */
-	void addLoader(ISimpleResourceLoader * loader, bool writeable);
-};
+	std::unordered_set<ResourceID> getFilteredFiles(std::function<bool(const ResourceID &)> filter) const override;
+	bool createResource(std::string filename, bool update = false) override;
+	std::vector<const ISimpleResourceLoader *> getResourcesWithName(const ResourceID & resourceName) const override;
+
+	/**
+	 * Adds a resource loader to the loaders list
+	 * Passes loader ownership to this object
+	 *
+	 * @param loader The simple resource loader object to add
+	 * @param writeable - resource shall be treated as writeable
+	 */
+	void addLoader(ISimpleResourceLoader * loader, bool writeable);
+};

+ 3 - 4
lib/filesystem/CArchiveLoader.cpp

@@ -5,7 +5,6 @@
 #include "CCompressedStream.h"
 
 #include "CBinaryReader.h"
-#include "CFileInfo.h"
 
 ArchiveEntry::ArchiveEntry()
 	: offset(0), fullSize(0), compressedSize(0)
@@ -140,13 +139,13 @@ std::unique_ptr<CInputStream> CArchiveLoader::load(const ResourceID & resourceNa
 
 	if (entry.compressedSize != 0) //compressed data
 	{
-		std::unique_ptr<CInputStream> fileStream(new CFileInputStream(archive, entry.offset, entry.compressedSize));
+		auto fileStream = make_unique<CFileInputStream>(archive, entry.offset, entry.compressedSize);
 
-		return std::unique_ptr<CInputStream>(new CCompressedStream(std::move(fileStream), false, entry.fullSize));
+		return make_unique<CCompressedStream>(std::move(fileStream), false, entry.fullSize);
 	}
 	else
 	{
-		return std::unique_ptr<CInputStream>(new CFileInputStream(archive, entry.offset, entry.fullSize));
+		return make_unique<CFileInputStream>(archive, entry.offset, entry.fullSize);
 	}
 }
 

+ 0 - 1
lib/filesystem/CArchiveLoader.h

@@ -13,7 +13,6 @@
 #include "ISimpleResourceLoader.h"
 #include "ResourceID.h"
 
-class CFileInfo;
 class CFileInputStream;
 
 /**

+ 0 - 96
lib/filesystem/CFileInfo.cpp

@@ -1,96 +0,0 @@
-#include "StdInc.h"
-#include "CFileInfo.h"
-
-CFileInfo::CFileInfo() : name("")
-{
-
-}
-
-CFileInfo::CFileInfo(std::string name)
-	: name(std::move(name))
-{
-
-}
-
-bool CFileInfo::exists() const
-{
-	return boost::filesystem::exists(name);
-}
-
-bool CFileInfo::isDirectory() const
-{
-	return boost::filesystem::is_directory(name);
-}
-
-void CFileInfo::setName(const std::string & name)
-{
-	this->name = name;
-}
-
-std::string CFileInfo::getName() const
-{
-	return name;
-}
-
-std::string CFileInfo::getPath() const
-{
-	size_t found = name.find_last_of("/\\");
-	return name.substr(0, found);
-}
-
-std::string CFileInfo::getExtension() const
-{
-	// Get position of file extension dot
-	size_t dotPos = name.find_last_of('.');
-
-	if(dotPos != std::string::npos)
-		return name.substr(dotPos);
-
-	return "";
-}
-
-std::string CFileInfo::getFilename() const
-{
-	const size_t found = name.find_last_of("/\\");
-	return name.substr(found + 1);
-}
-
-std::string CFileInfo::getStem() const
-{
-	std::string rslt = name;
-
-	// Remove file extension
-	const size_t dotPos = name.find_last_of('.');
-
-	if(dotPos != std::string::npos)
-		rslt.erase(dotPos);
-
-	return rslt;
-}
-
-std::string CFileInfo::getBaseName() const
-{
-	size_t begin = name.find_last_of("/\\");
-	size_t end = name.find_last_of(".");
-
-	if(begin == std::string::npos)
-		begin = 0;
-	else
-		++begin;
-	
-	if (end < begin)
-		end = std::string::npos;
-
-	size_t len = (end == std::string::npos ? std::string::npos : end - begin);
-	return name.substr(begin, len);
-}
-
-EResType::Type CFileInfo::getType() const
-{
-	return EResTypeHelper::getTypeFromExtension(getExtension());
-}
-
-std::time_t CFileInfo::getDate() const
-{
-	return boost::filesystem::last_write_time(name);
-}

+ 0 - 113
lib/filesystem/CFileInfo.h

@@ -1,113 +0,0 @@
-#pragma once
-
-/*
- * CFileInfo.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 "ResourceID.h"
-
-/**
- * A class which holds information about a file.
- */
-class DLL_LINKAGE CFileInfo
-{
-public:
-	/**
-	 * Default ctor.
-	 */
-	CFileInfo();
-
-	/**
-	 * Ctor.
-	 *
-	 * @param name The path and name of the file.
-	 */
-	explicit CFileInfo(std::string name);
-
-	/**
-	 * Checks if the file exists.
-	 *
-	 * @return true if the file exists, false if not.
-	 */
-	bool exists() const;
-
-	/**
-	 * Checks if the file is a directory.
-	 *
-	 * @return true if the file is a directory, false if not.
-	 */
-	bool isDirectory() const;
-
-	/**
-	 * Sets the name.
-	 *
-	 * @param name The name of the file
-	 */
-	void setName(const std::string & name);
-
-	/**
-	 * Gets the name of the file.
-	 *
-	 * @return the path and name of the file. E.g. ./dir/file.ext
-	 */
-	std::string getName() const;
-
-	/**
-	 * Gets the path to the file only.
-	 *
-	 * @return the path to the file only. E.g. ./dir/
-	 */
-	std::string getPath() const;
-
-	/**
-	 * Gets the file extension.
-	 *
-	 * @return the file extension. E.g. .ext
-	 */
-	std::string getExtension() const;
-
-	/**
-	 * Returns the name of the file.
-	 *
-	 * @return the name of the file. E.g. foo.txt
-	 */
-	std::string getFilename() const;
-
-	/**
-	 * Gets the file name + path exclusive the extension of the file.
-	 *
-	 * @return the file name exclusive the extension of the file. E.g. ./dir/foo
-	 */
-	std::string getStem() const;
-
-	/**
-	 * Gets the file name exclusive the extension of the file.
-	 *
-	 * @return the file name exclusive the extension and a path of the file. E.g. foo
-	 */
-	std::string getBaseName() const;
-
-	/**
-	 * Gets the extension type as a EResType enumeration.
-	 *
-	 * @return the extension type as a EResType enumeration.
-	 */
-	EResType::Type getType() const;
-
-	/**
-	 * Gets the timestamp of the file.
-	 *
-	 * @return the timestamp of the file, 0 if no timestamp was set
-	 */
-	std::time_t getDate() const;
-
-private:
-	/** Contains the original URI(not modified) e.g. ./dir/foo.txt */
-	std::string name;
-};

+ 0 - 18
lib/filesystem/CFileInputStream.cpp

@@ -1,8 +1,6 @@
 #include "StdInc.h"
 #include "CFileInputStream.h"
 
-#include "CFileInfo.h"
-
 CFileInputStream::CFileInputStream(const boost::filesystem::path & file, si64 start, si64 size)
   : dataStart{start},
 	dataSize{size},
@@ -20,22 +18,6 @@ CFileInputStream::CFileInputStream(const boost::filesystem::path & file, si64 st
 	fileStream.seekg(dataStart, std::ios::beg);
 }
 
-CFileInputStream::CFileInputStream(const CFileInfo & file, si64 start, si64 size)
-  : dataStart{start},
-	dataSize{size},
-	fileStream{file.getName(), std::ios::in | std::ios::binary}
-{
-	if (fileStream.fail())
-		throw std::runtime_error("File " + file.getName() + " isn't available.");
-
-	if (dataSize == 0)
-	{
-		fileStream.seekg(0, std::ios::end);
-		dataSize = tell();
-	}
-
-	fileStream.seekg(dataStart, std::ios::beg);
-}
 
 si64 CFileInputStream::read(ui8 * data, si64 size)
 {

+ 0 - 9
lib/filesystem/CFileInputStream.h

@@ -13,8 +13,6 @@
 #include "CInputStream.h"
 #include "FileStream.h"
 
-class CFileInfo;
-
 /**
  * A class which provides method definitions for reading a file from the filesystem.
  */
@@ -32,13 +30,6 @@ public:
 	 */
 	CFileInputStream(const boost::filesystem::path & file, si64 start = 0, si64 size = 0);
 
-	/**
-	 * C-tor. Opens the specified file.
-	 *
-	 * @see CFileInputStream::CFileInputStream(const boost::filesystem::path &, si64, si64)
-	 */
-	CFileInputStream(const CFileInfo & file, si64 start=0, si64 size=0);
-
 	/**
 	 * Reads n bytes from the stream into the data buffer.
 	 *

+ 1 - 3
lib/filesystem/CFilesystemLoader.cpp

@@ -1,7 +1,6 @@
 #include "StdInc.h"
 #include "CFilesystemLoader.h"
 
-#include "CFileInfo.h"
 #include "CFileInputStream.h"
 #include "FileStream.h"
 
@@ -19,8 +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)));
-	return stream;
+	return make_unique<CFileInputStream>(baseDirectory / fileList.at(resourceName));
 }
 
 bool CFilesystemLoader::existsResource(const ResourceID & resourceName) const

+ 0 - 1
lib/filesystem/CFilesystemLoader.h

@@ -13,7 +13,6 @@
 #include "ISimpleResourceLoader.h"
 #include "ResourceID.h"
 
-class CFileInfo;
 class CInputStream;
 
 /**

+ 56 - 0
lib/filesystem/FileInfo.cpp

@@ -0,0 +1,56 @@
+#include "StdInc.h"
+
+#include "FileInfo.h"
+
+namespace FileInfo
+{
+
+boost::string_ref GetFilename(boost::string_ref path)
+{
+	const auto pos = path.find_last_of("/\\");
+
+	if (pos != boost::string_ref::npos)
+		return path.substr(pos + 1);
+
+	return path;
+}
+
+boost::string_ref GetExtension(boost::string_ref path)
+{
+	const auto dotPos = path.find_last_of('.');
+
+	if(dotPos != boost::string_ref::npos)
+		return path.substr(dotPos);
+
+	return boost::string_ref{};
+}
+
+boost::string_ref GetStem(boost::string_ref path)
+{
+	auto begin	= path.find_last_of("/\\");
+	auto end	= path.find_last_of('.');
+
+	if (begin == boost::string_ref::npos)
+		begin = 0;
+	else
+		begin += 1;
+
+	if (end < begin)
+		end = boost::string_ref::npos;
+
+	return path.substr(begin, end);
+}
+
+boost::string_ref GetParentPath(boost::string_ref path)
+{
+	const auto pos = path.find_last_of("/\\");
+	return path.substr(0, pos);
+}
+
+boost::string_ref GetPathStem(boost::string_ref path)
+{
+	const auto dotPos = path.find_last_of('.');
+	return path.substr(0, dotPos);
+}
+
+} // namespace FileInfo

+ 53 - 0
lib/filesystem/FileInfo.h

@@ -0,0 +1,53 @@
+#pragma once
+
+/*
+ * FileInfo.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/utility/string_ref.hpp>
+
+namespace FileInfo
+{
+
+/**
+ * Returns the name of the file.
+ *
+ * @return the name of the file. E.g. foo.txt
+ */
+boost::string_ref DLL_LINKAGE GetFilename(boost::string_ref path);
+
+/**
+ * Gets the file extension.
+ *
+ * @return the file extension. E.g. .ext
+ */
+boost::string_ref DLL_LINKAGE GetExtension(boost::string_ref path);
+
+/**
+ * Gets the file name exclusive the extension of the file.
+ *
+ * @return the file name exclusive the extension and the path of the file. E.g. foo
+ */
+boost::string_ref DLL_LINKAGE GetStem(boost::string_ref path);
+
+/**
+ * Gets the path to the file only.
+ *
+ * @return the path to the file only. E.g. ./dir/
+ */
+boost::string_ref DLL_LINKAGE GetParentPath(boost::string_ref path);
+
+/**
+ * Gets the file name + path exclusive the extension of the file.
+ *
+ * @return the file name exclusive the extension of the file. E.g. ./dir/foo
+ */
+boost::string_ref DLL_LINKAGE GetPathStem(boost::string_ref path);
+
+} // namespace FileInfo

+ 0 - 2
lib/filesystem/Filesystem.cpp

@@ -1,8 +1,6 @@
 #include "StdInc.h"
 #include "Filesystem.h"
 
-#include "CFileInfo.h"
-
 #include "CArchiveLoader.h"
 #include "CFilesystemLoader.h"
 #include "AdapterLoaders.h"

+ 32 - 25
lib/filesystem/ResourceID.cpp

@@ -1,7 +1,6 @@
 #include "StdInc.h"
 #include "ResourceID.h"
-
-#include "CFileInfo.h"
+#include "FileInfo.h"
 
 // trivial to_upper that completely ignores localization and only work with ASCII
 // Technically not a problem since
@@ -23,30 +22,47 @@ static inline void toUpper(std::string & string)
 	for (char & symbol : string)
 		toUpper(symbol);
 }
-
+#else
+static inline void toUpper(std::string & string)
+{
+	boost::to_upper(string);
+}
 #endif
 
-
-ResourceID::ResourceID()
-	:type(EResType::OTHER)
+static inline EResType::Type readType(const std::string& name)
 {
+	return EResTypeHelper::getTypeFromExtension(FileInfo::GetExtension(name).to_string());
 }
 
-ResourceID::ResourceID(std::string name)
-	:type(EResType::UNDEFINED)
+static inline std::string readName(std::string name)
 {
-	CFileInfo info(std::move(name));
-	setType(info.getType());
-	setName(info.getStem());
+	const auto dotPos = name.find_last_of('.');
+
+	if (dotPos != std::string::npos)
+		name.resize(dotPos);
+
+	toUpper(name);
+
+	return name;
 }
 
-ResourceID::ResourceID(std::string name, EResType::Type type)
-	:type(EResType::UNDEFINED)
+#if 0
+ResourceID::ResourceID()
+	:type(EResType::OTHER)
 {
-	setType(type);
-	setName(std::move(name));
 }
+#endif
 
+ResourceID::ResourceID(std::string name_):
+	type{readType(name_)},
+	name{readName(std::move(name_))}
+{}
+
+ResourceID::ResourceID(std::string name_, EResType::Type type_):
+	type{type_},
+	name{readName(std::move(name_))}
+{}
+#if 0
 std::string ResourceID::getName() const
 {
 	return name;
@@ -72,26 +88,17 @@ void ResourceID::setName(std::string name)
 		this->name.erase(dotPos);
 	}
 
-#ifdef ENABLE_TRIVIAL_TOUPPER
 	toUpper(this->name);
-#else
-	// strangely enough but this line takes 40-50% of filesystem loading time
-	boost::to_upper(this->name);
-#endif
 }
 
 void ResourceID::setType(EResType::Type type)
 {
 	this->type = type;
 }
-
+#endif
 EResType::Type EResTypeHelper::getTypeFromExtension(std::string extension)
 {
-#ifdef ENABLE_TRIVIAL_TOUPPER
 	toUpper(extension);
-#else
-	boost::to_upper(extension);
-#endif
 
 	static const std::map<std::string, EResType::Type> stringToRes =
 	{

+ 8 - 8
lib/filesystem/ResourceID.h

@@ -70,7 +70,7 @@ public:
 	/**
 	 * Default c-tor.
 	 */
-	ResourceID();
+	//ResourceID();
 
 	/**
 	 * Ctor. Can be used to create identifier for resource loading using one parameter
@@ -98,20 +98,20 @@ public:
 		return name == other.name && type == other.type;
 	}
 
-	std::string getName() const;
-	EResType::Type getType() const;
-	void setName(std::string name);
-	void setType(EResType::Type type);
+	std::string		getName() const {return name;}
+	EResType::Type	getType() const {return type;}
+	//void setName(std::string name);
+	//void setType(EResType::Type type);
 
 private:
-	/** Specifies the resource name. No extension so .pcx and .png can override each other, always in upper case. **/
-	std::string name;
-
 	/**
 	 * Specifies the resource type. EResType::OTHER if not initialized.
 	 * Required to prevent conflicts if files with different types (e.g. text and image) have the same name.
 	 */
 	EResType::Type type;
+
+	/** Specifies the resource name. No extension so .pcx and .png can override each other, always in upper case. **/
+	std::string name;
 };
 
 namespace std

+ 8 - 1
lib/mapObjects/ObjectTemplate.cpp

@@ -348,11 +348,18 @@ void ObjectTemplate::writeJson(JsonNode & node, const bool withTerrain) const
 
 ui32 ObjectTemplate::getWidth() const
 {
-	return usedTiles.empty() ? 0 : usedTiles.front().size();
+	//TODO: Use 2D array
+	ui32 ret = 0;
+	for (auto row : usedTiles)
+	{
+		ret = std::max<ui32>(ret, row.size());
+	}
+	return ret;
 }
 
 ui32 ObjectTemplate::getHeight() const
 {
+	//TODO: Use 2D array
 	return usedTiles.size();
 }
 

+ 0 - 7
lib/rmg/CRmgTemplateZone.cpp

@@ -2074,13 +2074,6 @@ void CRmgTemplateZone::placeObject(CMapGenerator* gen, CGObjectInstance* object,
 			gen->setNearestObjectDistance(tile, std::min<float>(d, gen->getNearestObjectDistance(tile)));
 		}
 	}
-	if (object->ID == Obj::SEER_HUT) //debug
-	{
-		CGSeerHut * sh = dynamic_cast<CGSeerHut *>(object);
-		auto artid = sh->quest->m5arts.front();
-		logGlobal->warnStream() << boost::format("Placed Seer Hut at %s, quest artifact %d is %s") % object->pos % artid % VLC->arth->artifacts[artid]->Name();
-	}
-
 
 	switch (object->ID)
 	{

+ 6 - 6
server/CGameHandler.cpp

@@ -1,7 +1,7 @@
 #include "StdInc.h"
 
 #include "../lib/filesystem/Filesystem.h"
-#include "../lib/filesystem/CFileInfo.h"
+#include "../lib/filesystem/FileInfo.h"
 #include "../lib/int3.h"
 #include "../lib/mapping/CCampaignHandler.h"
 #include "../lib/StartInfo.h"
@@ -2413,13 +2413,13 @@ void CGameHandler::sendAndApply( NewStructures * info )
 void CGameHandler::save(const std::string & filename )
 {
     logGlobal->infoStream() << "Saving to " << filename;
-	CFileInfo info(filename);
-	//CResourceHandler::get("local")->createResource(info.getStem() + ".vlgm1");
-	CResourceHandler::get("local")->createResource(info.getStem() + ".vsgm1");
+	const auto stem	= FileInfo::GetPathStem(filename);
+	const auto savefname = stem.to_string() + ".vsgm1";
+	CResourceHandler::get("local")->createResource(savefname);
 
 	{
         logGlobal->infoStream() << "Ordering clients to serialize...";
-		SaveGame sg(info.getStem() + ".vcgm1");
+		SaveGame sg(savefname);
 		sendToAllClients(&sg);
 	}
 
@@ -2434,7 +2434,7 @@ void CGameHandler::save(const std::string & filename )
 // 		}
 
 		{
-			CSaveFile save(*CResourceHandler::get("local")->getResourceName(ResourceID(info.getStem(), EResType::SERVER_SAVEGAME)));
+			CSaveFile save(*CResourceHandler::get("local")->getResourceName(ResourceID(stem.to_string(), EResType::SERVER_SAVEGAME)));
 			saveCommonState(save);
             logGlobal->infoStream() << "Saving server state";
 			save << *this;

+ 3 - 5
server/VCMI_server.cbp

@@ -15,9 +15,8 @@
 				<Option compiler="gcc" />
 				<Option use_console_runner="0" />
 				<Compiler>
+					<Add option="-g" />
 					<Add option="-Og" />
-					<Add option="-ggdb" />
-					<Add directory="$(#zlib.include)" />
 				</Compiler>
 				<Linker>
 					<Add directory="$(#boost.lib32)" />
@@ -34,7 +33,6 @@
 				<Compiler>
 					<Add option="-fomit-frame-pointer" />
 					<Add option="-O2" />
-					<Add directory="$(#zlib.include)" />
 				</Compiler>
 				<Linker>
 					<Add option="-s" />
@@ -69,13 +67,13 @@
 			<Add option="-Wno-sign-compare" />
 			<Add option="-Wno-unused-parameter" />
 			<Add option="-Wno-overloaded-virtual" />
+			<Add option="-isystem $(#boost.include)" />
 			<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)" />
+			<Add directory="$(#zlib.include)" />
 		</Compiler>
 		<Linker>
 			<Add option="-lole32" />

+ 1 - 2
vcmi.workspace

@@ -6,8 +6,8 @@
 			<Depends filename="lib/minizip/minizip.cbp" />
 		</Project>
 		<Project filename="client/VCMI_client.cbp">
-			<Depends filename="server/VCMI_server.cbp" />
 			<Depends filename="lib/VCMI_lib.cbp" />
+			<Depends filename="server/VCMI_server.cbp" />
 		</Project>
 		<Project filename="server/VCMI_server.cbp">
 			<Depends filename="lib/VCMI_lib.cbp" />
@@ -31,7 +31,6 @@
 			<Depends filename="client/VCMI_client.cbp" />
 			<Depends filename="server/VCMI_server.cbp" />
 			<Depends filename="AI/EmptyAI/EmptyAI.cbp" />
-			<Depends filename="AI/VCAI/VCAI.cbp" />
 			<Depends filename="AI/StupidAI/StupidAI.cbp" />
 			<Depends filename="AI/BattleAI/BattleAI.cbp" />
 		</Project>