1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-01-12 02:28:11 +02:00

Provide encoding information to maps & campaigns loaders

This commit is contained in:
Ivan Savenko 2023-02-24 22:38:12 +02:00
parent bd70b6fabd
commit 4260726e4b
20 changed files with 121 additions and 68 deletions

View File

@ -15,6 +15,7 @@
#include "../../lib/CGeneralTextHandler.h"
#include "../../lib/StartInfo.h"
#include "../../lib/mapping/CMapInfo.h"
#include "../../lib/mapping/CMap.h"
#include "../gui/CGuiHandler.h"
#include "../CGameInfo.h"
#include "../CPlayerInterface.h"

View File

@ -24,6 +24,7 @@
#include "../../lib/StartInfo.h"
#include "../../lib/filesystem/Filesystem.h"
#include "../../lib/mapping/CMapInfo.h"
#include "../../lib/mapping/CMap.h"
CSavingScreen::CSavingScreen()
: CSelectionBase(ESelectionScreen::saveGame)

View File

@ -25,6 +25,7 @@
#include "../../lib/CGeneralTextHandler.h"
#include "../../lib/mapping/CMapInfo.h"
#include "../../lib/mapping/CMap.h"
#include "../../lib/rmg/CMapGenOptions.h"
#include "../../lib/CModHandler.h"
#include "../../lib/rmg/CRmgTemplateStorage.h"

View File

@ -33,6 +33,8 @@
#include "../../lib/CModHandler.h"
#include "../../lib/filesystem/Filesystem.h"
#include "../../lib/mapping/CMapInfo.h"
#include "../../lib/mapping/CMap.h"
#include "../../lib/mapping/CCampaignHandler.h"
#include "../../lib/serializer/Connection.h"
bool mapSorter::operator()(const std::shared_ptr<CMapInfo> aaa, const std::shared_ptr<CMapInfo> bbb)

View File

@ -217,7 +217,7 @@ std::vector<CIdentifierStorage::ObjectData> CIdentifierStorage::getPossibleIdent
// special scope that should have access to all in-game objects
if (request.localScope == CModHandler::scopeGame())
{
for (auto const & modName : VLC->modh->getActiveMods())
for(const auto & modName : VLC->modh->getActiveMods())
allowedScopes.insert(modName);
}
@ -943,8 +943,9 @@ std::vector<std::string> CModHandler::getModList(std::string path)
bool CModHandler::isScopeReserved(const TModID & scope)
{
static const std::array<TModID, 6> reservedScopes = {
"core", "map", "game", "root", "saves", "config"
//following scopes are reserved - either in use by mod system or by filesystem
static const std::array<TModID, 9> reservedScopes = {
"core", "map", "game", "root", "saves", "config", "local", "initial", "mapEditor"
};
return std::find(reservedScopes.begin(), reservedScopes.end(), scope) != reservedScopes.end();
@ -1097,8 +1098,22 @@ void CModHandler::loadModFilesystems()
}
}
std::string CModHandler::getModLanguage(TModID modId) const
TModID CModHandler::findResourceOrigin(const ResourceID & name)
{
for(const auto & modID : boost::adaptors::reverse(activeMods))
{
if(CResourceHandler::get(modID)->existsResource(name))
return modID;
}
assert(0);
return "";
}
std::string CModHandler::getModLanguage(const TModID& modId) const
{
if ( modId == "core")
return VLC->generaltexth->getInstalledLanguage();
return allMods.at(modId).baseLanguage;
}
@ -1130,7 +1145,7 @@ bool CModHandler::validateTranslations(TModID modName) const
result |= VLC->generaltexth->validateTranslation(mod.baseLanguage, modName, json);
}
for (auto const & language : Languages::getLanguageList())
for(const auto & language : Languages::getLanguageList())
{
if (!language.hasTranslation)
continue;
@ -1148,7 +1163,7 @@ bool CModHandler::validateTranslations(TModID modName) const
void CModHandler::loadTranslation(TModID modName)
{
auto const & mod = allMods[modName];
const auto & mod = allMods[modName];
std::string preferredLanguage = VLC->generaltexth->getPreferredLanguage();
std::string modBaseLanguage = allMods[modName].baseLanguage;

View File

@ -339,7 +339,10 @@ public:
void loadMods(bool onlyEssential = false);
void loadModFilesystems();
std::string getModLanguage(TModID modId) const;
/// returns ID of mod that provides selected file resource
TModID findResourceOrigin(const ResourceID & name);
std::string getModLanguage(const TModID& modId) const;
std::set<TModID> getModDependencies(TModID modId, bool & isModFound) const;

View File

@ -28,6 +28,8 @@
#include "StartInfo.h"
#include "CPlayerState.h"
#include "TerrainHandler.h"
#include "mapping/CCampaignHandler.h"
VCMI_LIB_NAMESPACE_BEGIN

View File

@ -13,6 +13,8 @@
#include "CGeneralTextHandler.h"
#include "rmg/CMapGenOptions.h"
#include "mapping/CMapInfo.h"
#include "mapping/CCampaignHandler.h"
#include "mapping/CMap.h"
VCMI_LIB_NAMESPACE_BEGIN

View File

@ -17,10 +17,13 @@
#include "../VCMI_Lib.h"
#include "../vcmi_endian.h"
#include "../CGeneralTextHandler.h"
#include "../TextOperations.h"
#include "../StartInfo.h"
#include "../CModHandler.h"
#include "../CArtHandler.h" //for hero crossover
#include "../mapObjects/CGHeroInstance.h"//for hero crossover
#include "../CHeroHandler.h"
#include "../Languages.h"
#include "CMapService.h"
#include "CMap.h"
#include "CMapInfo.h"
@ -40,31 +43,41 @@ bool CScenarioTravel::STravelBonus::isBonusForHero() const
CCampaignHeader CCampaignHandler::getHeader( const std::string & name)
{
std::vector<ui8> cmpgn = getFile(name, true)[0];
ResourceID resourceID(name, EResType::CAMPAIGN);
std::string modName = VLC->modh->findResourceOrigin(resourceID);
std::string language = VLC->modh->getModLanguage(modName);
std::string encoding = Languages::getLanguageOptions(language).encoding;
auto fileStream = CResourceHandler::get(modName)->load(resourceID);
std::vector<ui8> cmpgn = getFile(std::move(fileStream), true)[0];
CMemoryStream stream(cmpgn.data(), cmpgn.size());
CBinaryReader reader(&stream);
CCampaignHeader ret = readHeaderFromMemory(reader);
ret.filename = name;
CCampaignHeader ret = readHeaderFromMemory(reader, name, encoding);
return ret;
}
std::unique_ptr<CCampaign> CCampaignHandler::getCampaign( const std::string & name )
{
ResourceID resourceID(name, EResType::CAMPAIGN);
std::string modName = VLC->modh->findResourceOrigin(resourceID);
std::string language = VLC->modh->getModLanguage(modName);
std::string encoding = Languages::getLanguageOptions(language).encoding;
auto fileStream = CResourceHandler::get(modName)->load(resourceID);
auto ret = std::make_unique<CCampaign>();
std::vector<std::vector<ui8>> file = getFile(name, false);
std::vector<std::vector<ui8>> file = getFile(std::move(fileStream), false);
CMemoryStream stream(file[0].data(), file[0].size());
CBinaryReader reader(&stream);
ret->header = readHeaderFromMemory(reader);
ret->header.filename = name;
ret->header = readHeaderFromMemory(reader, name, encoding);
int howManyScenarios = static_cast<int>(VLC->generaltexth->getCampaignLength(ret->header.mapVersion));
for(int g=0; g<howManyScenarios; ++g)
{
CCampaignScenario sc = readScenarioFromMemory(reader, ret->header.version, ret->header.mapVersion);
CCampaignScenario sc = readScenarioFromMemory(reader, name, encoding, ret->header.version, ret->header.mapVersion);
ret->scenarios.push_back(sc);
}
@ -88,7 +101,8 @@ std::unique_ptr<CCampaign> CCampaignHandler::getCampaign( const std::string & na
auto hdr = mapService.loadMapHeader(
reinterpret_cast<const ui8 *>(ret->mapPieces[scenarioID].c_str()),
static_cast<int>(ret->mapPieces[scenarioID].size()),
scenarioName);
scenarioName,
"(unknown)");
ret->scenarios[scenarioID].scenarioName = hdr->name;
scenarioID++;
}
@ -110,28 +124,30 @@ std::unique_ptr<CCampaign> CCampaignHandler::getCampaign( const std::string & na
return ret;
}
std::string CCampaignHandler::readLocalizedString(CBinaryReader & reader)
std::string CCampaignHandler::readLocalizedString(CBinaryReader & reader, std::string encoding)
{
return reader.readBaseString();
return TextOperations::toUnicode(reader.readBaseString(), encoding);
}
CCampaignHeader CCampaignHandler::readHeaderFromMemory( CBinaryReader & reader )
CCampaignHeader CCampaignHandler::readHeaderFromMemory( CBinaryReader & reader, std::string filename, std::string encoding )
{
CCampaignHeader ret;
ret.version = reader.readUInt32();
ret.mapVersion = reader.readUInt8() - 1;//change range of it from [1, 20] to [0, 19]
ret.name = readLocalizedString(reader);
ret.description = readLocalizedString(reader);
ret.name = readLocalizedString(reader, encoding);
ret.description = readLocalizedString(reader, encoding);
if (ret.version > CampaignVersion::RoE)
ret.difficultyChoosenByPlayer = reader.readInt8();
else
ret.difficultyChoosenByPlayer = 0;
ret.music = reader.readInt8();
ret.filename = filename;
ret.encoding = encoding;
return ret;
}
CCampaignScenario CCampaignHandler::readScenarioFromMemory( CBinaryReader & reader, int version, int mapVersion )
CCampaignScenario CCampaignHandler::readScenarioFromMemory( CBinaryReader & reader, std::string filename, std::string encoding, int version, int mapVersion )
{
auto prologEpilogReader = [&]() -> CCampaignScenario::SScenarioPrologEpilog
{
@ -141,14 +157,14 @@ CCampaignScenario CCampaignHandler::readScenarioFromMemory( CBinaryReader & read
{
ret.prologVideo = reader.readUInt8();
ret.prologMusic = reader.readUInt8();
ret.prologText = readLocalizedString(reader);
ret.prologText = readLocalizedString(reader, encoding);
}
return ret;
};
CCampaignScenario ret;
ret.conquered = false;
ret.mapName = readLocalizedString(reader);
ret.mapName = readLocalizedString(reader, encoding);
ret.packedMapSize = reader.readUInt32();
if(mapVersion == 18)//unholy alliance
{
@ -160,7 +176,7 @@ CCampaignScenario CCampaignHandler::readScenarioFromMemory( CBinaryReader & read
}
ret.regionColor = reader.readUInt8();
ret.difficulty = reader.readUInt8();
ret.regionText = readLocalizedString(reader);
ret.regionText = readLocalizedString(reader, encoding);
ret.prolog = prologEpilogReader();
ret.epilog = prologEpilogReader();
@ -310,9 +326,9 @@ CScenarioTravel CCampaignHandler::readScenarioTravelFromMemory(CBinaryReader & r
return ret;
}
std::vector< std::vector<ui8> > CCampaignHandler::getFile(const std::string & name, bool headerOnly)
std::vector< std::vector<ui8> > CCampaignHandler::getFile(std::unique_ptr<CInputStream> file, bool headerOnly)
{
CCompressedStream stream(CResourceHandler::get()->load(ResourceID(name, EResType::CAMPAIGN)), true);
CCompressedStream stream(std::move(file), true);
std::vector< std::vector<ui8> > ret;
do
@ -457,7 +473,7 @@ CMap * CCampaignState::getMap(int scenarioId) const
std::string & mapContent = camp->mapPieces.find(scenarioId)->second;
const auto * buffer = reinterpret_cast<const ui8 *>(mapContent.data());
CMapService mapService;
return mapService.loadMap(buffer, static_cast<int>(mapContent.size()), scenarioName).release();
return mapService.loadMap(buffer, static_cast<int>(mapContent.size()), scenarioName, "(unknown)").release();
}
std::unique_ptr<CMapHeader> CCampaignState::getHeader(int scenarioId) const
@ -471,7 +487,7 @@ std::unique_ptr<CMapHeader> CCampaignState::getHeader(int scenarioId) const
std::string & mapContent = camp->mapPieces.find(scenarioId)->second;
const auto * buffer = reinterpret_cast<const ui8 *>(mapContent.data());
CMapService mapService;
return mapService.loadMapHeader(buffer, static_cast<int>(mapContent.size()), scenarioName);
return mapService.loadMapHeader(buffer, static_cast<int>(mapContent.size()), scenarioName, "(unknown)");
}
std::shared_ptr<CMapInfo> CCampaignState::getMapInfo(int scenarioId) const
@ -527,7 +543,4 @@ std::string CCampaignHandler::prologVoiceName(ui8 index)
return "";
}
VCMI_LIB_NAMESPACE_END

View File

@ -16,6 +16,7 @@ VCMI_LIB_NAMESPACE_BEGIN
struct StartInfo;
class CGHeroInstance;
class CBinaryReader;
class CInputStream;
class CMap;
class CMapHeader;
class CMapInfo;
@ -42,7 +43,7 @@ public:
ui8 music = 0; //CmpMusic.txt, start from 0
std::string filename;
ui8 loadFromLod = 0; //if true, this campaign must be loaded fro, .lod file
std::string encoding;
template <typename Handler> void serialize(Handler &h, const int formatVersion)
{
@ -53,7 +54,7 @@ public:
h & difficultyChoosenByPlayer;
h & music;
h & filename;
h & loadFromLod;
h & encoding;
}
};
@ -181,7 +182,7 @@ class DLL_LINKAGE CCampaignState
{
public:
std::unique_ptr<CCampaign> camp;
std::string campaignName;
std::string fileEncoding;
std::vector<ui8> mapsConquered, mapsRemaining;
boost::optional<si32> currentMap;
@ -206,7 +207,6 @@ public:
template <typename Handler> void serialize(Handler &h, const int version)
{
h & camp;
h & campaignName;
h & mapsRemaining;
h & mapsConquered;
h & currentMap;
@ -218,14 +218,15 @@ class DLL_LINKAGE CCampaignHandler
{
std::vector<size_t> scenariosCountPerCampaign;
static std::string readLocalizedString(CBinaryReader & reader);
static std::string readLocalizedString(CBinaryReader & reader, std::string encoding);
static CCampaignHeader readHeaderFromMemory(CBinaryReader & reader);
static CCampaignScenario readScenarioFromMemory(CBinaryReader & reader, int version, int mapVersion );
static CCampaignHeader readHeaderFromMemory(CBinaryReader & reader, std::string filename, std::string encoding);
static CCampaignScenario readScenarioFromMemory(CBinaryReader & reader, std::string filename, std::string encoding, int version, int mapVersion );
static CScenarioTravel readScenarioTravelFromMemory(CBinaryReader & reader, int version);
/// returns h3c split in parts. 0 = h3c header, 1-end - maps (binary h3m)
/// headerOnly - only header will be decompressed, returned vector wont have any maps
static std::vector< std::vector<ui8> > getFile(const std::string & name, bool headerOnly);
static std::vector<std::vector<ui8>> getFile(std::unique_ptr<CInputStream> file, bool headerOnly);
public:
static std::string prologVideoName(ui8 index);
static std::string prologMusicName(ui8 index);

View File

@ -14,6 +14,8 @@
#include "../StartInfo.h"
#include "../GameConstants.h"
#include "CMapService.h"
#include "CMap.h"
#include "CCampaignHandler.h"
#include "../filesystem/Filesystem.h"
#include "../serializer/CMemorySerializer.h"

View File

@ -9,21 +9,14 @@
*/
#pragma once
// Forward class declarations aren't enough here. The compiler
// generated CMapInfo d-tor, generates the std::unique_ptr d-tor as well here
// as a inline method. The std::unique_ptr d-tor requires a complete type. Defining
// the CMapInfo d-tor to let the compiler add the d-tor stuff in the .cpp file
// would work with one exception. It prevents the generation of the move
// constructor which is needed. (Writing such a c-tor is nasty.) With the
// new c++11 keyword "default" for constructors this problem could be solved. But it isn't
// available for Visual Studio for now. (Empty d-tor in .cpp would be required anyway)
#include "CMap.h"
#include "CCampaignHandler.h"
VCMI_LIB_NAMESPACE_BEGIN
struct StartInfo;
class CMapHeader;
class CCampaignHeader;
class ResourceID;
/**
* A class which stores the count of human players and all players, the filename,
* scenario options, the map header information,...
@ -44,7 +37,11 @@ public:
CMapInfo();
virtual ~CMapInfo();
CMapInfo &operator=(CMapInfo &&other);
CMapInfo(CMapInfo &&other) = delete;
CMapInfo(const CMapInfo &other) = delete;
CMapInfo &operator=(CMapInfo &&other) = delete;
CMapInfo &operator=(const CMapInfo &other) = delete;
void mapInit(const std::string & fname);
void saveInit(const ResourceID & file);

View File

@ -15,6 +15,8 @@
#include "../filesystem/CCompressedStream.h"
#include "../filesystem/CMemoryStream.h"
#include "../filesystem/CMemoryBuffer.h"
#include "../CModHandler.h"
#include "../Languages.h"
#include "CMap.h"
@ -26,20 +28,28 @@ VCMI_LIB_NAMESPACE_BEGIN
std::unique_ptr<CMap> CMapService::loadMap(const ResourceID & name) const
{
std::string modName = VLC->modh->findResourceOrigin(name);
std::string language = VLC->modh->getModLanguage(modName);
std::string encoding = Languages::getLanguageOptions(language).encoding;
auto stream = getStreamFromFS(name);
return getMapLoader(stream)->loadMap();
return getMapLoader(stream, name.getName(), encoding)->loadMap();
}
std::unique_ptr<CMapHeader> CMapService::loadMapHeader(const ResourceID & name) const
{
std::string modName = VLC->modh->findResourceOrigin(name);
std::string language = VLC->modh->getModLanguage(modName);
std::string encoding = Languages::getLanguageOptions(language).encoding;
auto stream = getStreamFromFS(name);
return getMapLoader(stream)->loadMapHeader();
return getMapLoader(stream, name.getName(), encoding)->loadMapHeader();
}
std::unique_ptr<CMap> CMapService::loadMap(const ui8 * buffer, int size, const std::string & name) const
std::unique_ptr<CMap> CMapService::loadMap(const ui8 * buffer, int size, const std::string & name, const std::string & encoding) const
{
auto stream = getStreamFromMem(buffer, size);
std::unique_ptr<CMap> map(getMapLoader(stream)->loadMap());
std::unique_ptr<CMap> map(getMapLoader(stream, name, encoding)->loadMap());
std::unique_ptr<CMapHeader> header(map.get());
//might be original campaign and require patch
@ -49,10 +59,10 @@ std::unique_ptr<CMap> CMapService::loadMap(const ui8 * buffer, int size, const s
return map;
}
std::unique_ptr<CMapHeader> CMapService::loadMapHeader(const ui8 * buffer, int size, const std::string & name) const
std::unique_ptr<CMapHeader> CMapService::loadMapHeader(const ui8 * buffer, int size, const std::string & name, const std::string & encoding) const
{
auto stream = getStreamFromMem(buffer, size);
std::unique_ptr<CMapHeader> header = getMapLoader(stream)->loadMapHeader();
std::unique_ptr<CMapHeader> header = getMapLoader(stream, name, encoding)->loadMapHeader();
//might be original campaign and require patch
getMapPatcher(name)->patchMapHeader(header);
@ -86,7 +96,7 @@ std::unique_ptr<CInputStream> CMapService::getStreamFromMem(const ui8 * buffer,
return std::unique_ptr<CInputStream>(new CMemoryStream(buffer, size));
}
std::unique_ptr<IMapLoader> CMapService::getMapLoader(std::unique_ptr<CInputStream> & stream)
std::unique_ptr<IMapLoader> CMapService::getMapLoader(std::unique_ptr<CInputStream> & stream, std::string mapName, std::string encoding)
{
// Read map header
CBinaryReader reader(stream.get());
@ -109,12 +119,12 @@ std::unique_ptr<IMapLoader> CMapService::getMapLoader(std::unique_ptr<CInputStre
// gzip header magic number, reversed for LE
case 0x00088B1F:
stream = std::unique_ptr<CInputStream>(new CCompressedStream(std::move(stream), true));
return std::unique_ptr<IMapLoader>(new CMapLoaderH3M(stream.get()));
return std::unique_ptr<IMapLoader>(new CMapLoaderH3M(mapName, encoding, stream.get()));
case EMapFormat::WOG :
case EMapFormat::AB :
case EMapFormat::ROE :
case EMapFormat::SOD :
return std::unique_ptr<IMapLoader>(new CMapLoaderH3M(stream.get()));
return std::unique_ptr<IMapLoader>(new CMapLoaderH3M(mapName, encoding, stream.get()));
default :
throw std::runtime_error("Unknown map format");
}

View File

@ -58,7 +58,7 @@ public:
* @param name indicates name of file that will be used during map header patching
* @return a unique ptr to the loaded map class
*/
virtual std::unique_ptr<CMap> loadMap(const ui8 * buffer, int size, const std::string & name) const = 0;
virtual std::unique_ptr<CMap> loadMap(const ui8 * buffer, int size, const std::string & name, const std::string & encoding) const = 0;
/**
* Loads the VCMI/H3 map header from a buffer. This method is temporarily
@ -72,7 +72,7 @@ public:
* @param name indicates name of file that will be used during map header patching
* @return a unique ptr to the loaded map class
*/
virtual std::unique_ptr<CMapHeader> loadMapHeader(const ui8 * buffer, int size, const std::string & name) const = 0;
virtual std::unique_ptr<CMapHeader> loadMapHeader(const ui8 * buffer, int size, const std::string & name, const std::string & encoding) const = 0;
virtual void saveMap(const std::unique_ptr<CMap> & map, boost::filesystem::path fullPath) const = 0;
};
@ -85,8 +85,8 @@ public:
std::unique_ptr<CMap> loadMap(const ResourceID & name) const override;
std::unique_ptr<CMapHeader> loadMapHeader(const ResourceID & name) const override;
std::unique_ptr<CMap> loadMap(const ui8 * buffer, int size, const std::string & name) const override;
std::unique_ptr<CMapHeader> loadMapHeader(const ui8 * buffer, int size, const std::string & name) const override;
std::unique_ptr<CMap> loadMap(const ui8 * buffer, int size, const std::string & name, const std::string & encoding) const override;
std::unique_ptr<CMapHeader> loadMapHeader(const ui8 * buffer, int size, const std::string & name, const std::string & encoding) const override;
void saveMap(const std::unique_ptr<CMap> & map, boost::filesystem::path fullPath) const override;
private:
/**
@ -113,7 +113,7 @@ private:
* @param stream the input map stream
* @return the constructed map loader
*/
static std::unique_ptr<IMapLoader> getMapLoader(std::unique_ptr<CInputStream> & stream);
static std::unique_ptr<IMapLoader> getMapLoader(std::unique_ptr<CInputStream> & stream, std::string mapName, std::string encoding);
/**
* Gets a map patcher for specified scenario

View File

@ -34,7 +34,7 @@ VCMI_LIB_NAMESPACE_BEGIN
const bool CMapLoaderH3M::IS_PROFILING_ENABLED = false;
CMapLoaderH3M::CMapLoaderH3M(CInputStream * stream)
CMapLoaderH3M::CMapLoaderH3M(const std::string & mapName, const std::string & encodingName, CInputStream * stream)
: map(nullptr)
, reader(new CBinaryReader(stream))
, inputStream(stream)

View File

@ -39,7 +39,7 @@ public:
*
* @param stream a stream containing the map data
*/
CMapLoaderH3M(CInputStream * stream);
CMapLoaderH3M(const std::string & mapName, const std::string & encodingName, CInputStream * stream);
/**
* Destructor.

View File

@ -23,6 +23,7 @@
#include "../CRandomGenerator.h"
#include "Functions.h"
#include "../mapping/CMapEditManager.h"
#include "../mapping/CMap.h"
VCMI_LIB_NAMESPACE_BEGIN

View File

@ -14,6 +14,7 @@
#include "CMapGenOptions.h"
#include "Zone.h"
#include "../mapping/CMapEditManager.h"
#include "../mapping/CMap.h"
#include "../CTownHandler.h"
#include "ObjectManager.h"
#include "RoadPlacer.h"

View File

@ -11,10 +11,10 @@
#pragma once
#include "../int3.h"
#include "../GameConstants.h"
#include "../mapping/CMap.h"
VCMI_LIB_NAMESPACE_BEGIN
class CMap;
class CMapEditManager;
class TileInfo;
class CMapGenOptions;

View File

@ -20,6 +20,7 @@
#include "../TerrainHandler.h"
#include "../CRandomGenerator.h"
#include "../mapping/CMapEditManager.h"
#include "../mapping/CMap.h"
VCMI_LIB_NAMESPACE_BEGIN