mirror of
https://github.com/minetest/minetestmapper.git
synced 2024-11-21 23:13:53 +01:00
Fix compatibility of MapBlock decoding
also properly drop support for version < 22, which hasn't worked in years
This commit is contained in:
parent
92f6b051a5
commit
2979dc5b6b
@ -11,20 +11,18 @@ static inline uint16_t readU16(const unsigned char *data)
|
||||
return data[0] << 8 | data[1];
|
||||
}
|
||||
|
||||
static int readBlockContent(const unsigned char *mapData, u8 version, unsigned int datapos)
|
||||
static int readBlockContent(const unsigned char *mapData, u8 contentWidth, unsigned int datapos)
|
||||
{
|
||||
if (version >= 24) {
|
||||
if (contentWidth == 2) {
|
||||
size_t index = datapos << 1;
|
||||
return (mapData[index] << 8) | mapData[index + 1];
|
||||
} else if (version >= 20) {
|
||||
if (mapData[datapos] <= 0x80)
|
||||
return mapData[datapos];
|
||||
} else {
|
||||
u8 param = mapData[datapos];
|
||||
if (param <= 0x7f)
|
||||
return param;
|
||||
else
|
||||
return (int(mapData[datapos]) << 4) | (int(mapData[datapos + 0x2000]) >> 4);
|
||||
return (int(param) << 4) | (int(mapData[datapos + 0x2000]) >> 4);
|
||||
}
|
||||
std::ostringstream oss;
|
||||
oss << "Unsupported map version " << version;
|
||||
throw std::runtime_error(oss.str());
|
||||
}
|
||||
|
||||
BlockDecoder::BlockDecoder()
|
||||
@ -39,6 +37,7 @@ void BlockDecoder::reset()
|
||||
m_nameMap.clear();
|
||||
|
||||
m_version = 0;
|
||||
m_contentWidth = 0;
|
||||
m_mapData = ustring();
|
||||
}
|
||||
|
||||
@ -50,16 +49,30 @@ void BlockDecoder::decode(const ustring &datastr)
|
||||
|
||||
uint8_t version = data[0];
|
||||
//uint8_t flags = data[1];
|
||||
if (version < 22) {
|
||||
std::ostringstream oss;
|
||||
oss << "Unsupported map version " << (int)version;
|
||||
throw std::runtime_error(oss.str());
|
||||
}
|
||||
m_version = version;
|
||||
|
||||
size_t dataOffset = 0;
|
||||
if (version >= 27)
|
||||
dataOffset = 6;
|
||||
else if (version >= 22)
|
||||
dataOffset = 4;
|
||||
else
|
||||
dataOffset = 2;
|
||||
|
||||
uint8_t contentWidth = data[dataOffset];
|
||||
dataOffset++;
|
||||
uint8_t paramsWidth = data[dataOffset];
|
||||
dataOffset++;
|
||||
if (contentWidth != 1 && contentWidth != 2)
|
||||
throw std::runtime_error("unsupported map version (contentWidth)");
|
||||
if (paramsWidth != 2)
|
||||
throw std::runtime_error("unsupported map version (paramsWidth)");
|
||||
m_contentWidth = contentWidth;
|
||||
|
||||
|
||||
ZlibDecompressor decompressor(data, length);
|
||||
decompressor.setSeekPos(dataOffset);
|
||||
m_mapData = decompressor.decompress();
|
||||
@ -67,8 +80,6 @@ void BlockDecoder::decode(const ustring &datastr)
|
||||
dataOffset = decompressor.seekPos();
|
||||
|
||||
// Skip unused data
|
||||
if (version <= 21)
|
||||
dataOffset += 2;
|
||||
if (version == 23)
|
||||
dataOffset += 1;
|
||||
if (version == 24) {
|
||||
@ -92,7 +103,7 @@ void BlockDecoder::decode(const ustring &datastr)
|
||||
dataOffset += 4; // Skip timestamp
|
||||
|
||||
// Read mapping
|
||||
if (version >= 22) {
|
||||
{
|
||||
dataOffset++; // mapping version
|
||||
uint16_t numMappings = readU16(data + dataOffset);
|
||||
dataOffset += 2;
|
||||
@ -130,7 +141,7 @@ bool BlockDecoder::isEmpty() const
|
||||
std::string BlockDecoder::getNode(u8 x, u8 y, u8 z) const
|
||||
{
|
||||
unsigned int position = x + (y << 4) + (z << 8);
|
||||
int content = readBlockContent(m_mapData.c_str(), m_version, position);
|
||||
int content = readBlockContent(m_mapData.c_str(), m_contentWidth, position);
|
||||
if (content == m_blockAirId || content == m_blockIgnoreId)
|
||||
return "";
|
||||
NameMap::const_iterator it = m_nameMap.find(content);
|
||||
|
@ -20,7 +20,7 @@ private:
|
||||
int m_blockAirId;
|
||||
int m_blockIgnoreId;
|
||||
|
||||
u8 m_version;
|
||||
u8 m_version, m_contentWidth;
|
||||
ustring m_mapData;
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user