1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-11-25 22:42:04 +02:00

Moved roads and rivers to TerrainTypeHandler, by analogy to TerrainType.

This commit is contained in:
Tomasz Zieliński
2022-09-23 16:24:01 +02:00
parent 6aaf77812b
commit ebe45d512d
20 changed files with 392 additions and 190 deletions

View File

@@ -942,96 +942,107 @@ void CMapLoaderJson::readHeader(const bool complete)
void CMapLoaderJson::readTerrainTile(const std::string & src, TerrainTile & tile)
{
using namespace TerrainDetail;
{//terrain type
const std::string typeCode = src.substr(0, 2);
tile.terType = const_cast<TerrainType *>(VLC->terrainTypeHandler->getInfoByCode(typeCode));
}
int startPos = 2; //0+typeCode fixed length
{//terrain view
int pos = startPos;
while(isdigit(src.at(pos)))
pos++;
int len = pos - startPos;
if(len<=0)
throw std::runtime_error("Invalid terrain view in "+src);
const std::string rawCode = src.substr(startPos, len);
tile.terView = atoi(rawCode.c_str());
startPos+=len;
}
{//terrain flip
int terrainFlip = vstd::find_pos(flipCodes, src.at(startPos++));
if(terrainFlip < 0)
throw std::runtime_error("Invalid terrain flip in "+src);
else
tile.extTileFlags = terrainFlip;
}
if(startPos >= src.size())
return;
bool hasRoad = true;
{//road type
const std::string typeCode = src.substr(startPos, 2);
startPos+=2;
if(vstd::find_pos(ROAD_NAMES, typeCode) < 0)
{
if(vstd::find_pos(RIVER_NAMES, typeCode) < 0)
throw std::runtime_error("Invalid river type in "+src);
else
{
tile.riverType = typeCode;
hasRoad = false;
}
try
{
using namespace TerrainDetail;
{//terrain type
const std::string typeCode = src.substr(0, 2);
tile.terType = const_cast<TerrainType*>(VLC->terrainTypeHandler->getInfoByCode(typeCode));
}
int startPos = 2; //0+typeCode fixed length
{//terrain view
int pos = startPos;
while (isdigit(src.at(pos)))
pos++;
int len = pos - startPos;
if (len <= 0)
throw std::runtime_error("Invalid terrain view in " + src);
const std::string rawCode = src.substr(startPos, len);
tile.terView = atoi(rawCode.c_str());
startPos += len;
}
{//terrain flip
int terrainFlip = vstd::find_pos(flipCodes, src.at(startPos++));
if (terrainFlip < 0)
throw std::runtime_error("Invalid terrain flip in " + src);
else
tile.extTileFlags = terrainFlip;
}
if (startPos >= src.size())
return;
bool hasRoad = true;
//FIXME: check without exceptions?
{//road type
const std::string typeCode = src.substr(startPos, 2);
startPos += 2;
try
{
tile.roadType = const_cast<RoadType*>(VLC->terrainTypeHandler->getRoadByCode(typeCode));
}
catch (const std::exception& e) //it's not a road, it's a river
{
try
{
tile.riverType = const_cast<RiverType*>(VLC->terrainTypeHandler->getRiverByCode(typeCode));
hasRoad = false;
}
catch (const std::exception& e)
{
throw std::runtime_error("Invalid river type in " + src);
}
}
}
if (hasRoad)
{//road dir
int pos = startPos;
while (isdigit(src.at(pos)))
pos++;
int len = pos - startPos;
if (len <= 0)
throw std::runtime_error("Invalid road dir in " + src);
const std::string rawCode = src.substr(startPos, len);
tile.roadDir = atoi(rawCode.c_str());
startPos += len;
}
if (hasRoad)
{//road flip
int flip = vstd::find_pos(flipCodes, src.at(startPos++));
if (flip < 0)
throw std::runtime_error("Invalid road flip in " + src);
else
tile.extTileFlags |= (flip << 4);
}
if (startPos >= src.size())
return;
if (hasRoad)
{//river type
const std::string typeCode = src.substr(startPos, 2);
startPos += 2;
tile.riverType = const_cast<RiverType*>(VLC->terrainTypeHandler->getRiverByCode(typeCode));
}
{//river dir
int pos = startPos;
while (isdigit(src.at(pos)))
pos++;
int len = pos - startPos;
if (len <= 0)
throw std::runtime_error("Invalid river dir in " + src);
const std::string rawCode = src.substr(startPos, len);
tile.riverDir = atoi(rawCode.c_str());
startPos += len;
}
{//river flip
int flip = vstd::find_pos(flipCodes, src.at(startPos++));
if (flip < 0)
throw std::runtime_error("Invalid road flip in " + src);
else
tile.extTileFlags |= (flip << 2);
}
else
tile.roadType = typeCode;
}
if(hasRoad)
{//road dir
int pos = startPos;
while(isdigit(src.at(pos)))
pos++;
int len = pos - startPos;
if(len<=0)
throw std::runtime_error("Invalid road dir in "+src);
const std::string rawCode = src.substr(startPos, len);
tile.roadDir = atoi(rawCode.c_str());
startPos+=len;
}
if(hasRoad)
{//road flip
int flip = vstd::find_pos(flipCodes, src.at(startPos++));
if(flip < 0)
throw std::runtime_error("Invalid road flip in "+src);
else
tile.extTileFlags |= (flip<<4);
}
if(startPos >= src.size())
return;
if(hasRoad)
{//river type
const std::string typeCode = src.substr(startPos, 2);
startPos+=2;
if(vstd::find_pos(RIVER_NAMES, typeCode) < 0)
throw std::runtime_error("Invalid river type in "+src);
tile.riverType = typeCode;
}
{//river dir
int pos = startPos;
while(isdigit(src.at(pos)))
pos++;
int len = pos - startPos;
if(len<=0)
throw std::runtime_error("Invalid river dir in "+src);
const std::string rawCode = src.substr(startPos, len);
tile.riverDir = atoi(rawCode.c_str());
startPos+=len;
}
{//river flip
int flip = vstd::find_pos(flipCodes, src.at(startPos++));
if(flip < 0)
throw std::runtime_error("Invalid road flip in "+src);
else
tile.extTileFlags |= (flip<<2);
catch (const std::exception & e)
{
logGlobal->error("Failed to read terrain tile: %s");
}
}
@@ -1278,10 +1289,10 @@ std::string CMapSaverJson::writeTerrainTile(const TerrainTile & tile)
out << tile.terType->typeCode << (int)tile.terView << flipCodes[tile.extTileFlags % 4];
if(tile.roadType != ROAD_NAMES[0])
if(tile.roadType->id != Road::NO_ROAD)
out << tile.roadType << (int)tile.roadDir << flipCodes[(tile.extTileFlags >> 4) % 4];
if(tile.riverType != RIVER_NAMES[0])
if(tile.riverType->id != River::NO_RIVER)
out << tile.riverType << (int)tile.riverDir << flipCodes[(tile.extTileFlags >> 2) % 4];
return out.str();