mirror of
https://github.com/minetest/minetestmapper.git
synced 2024-11-24 16:33:47 +01:00
Refactoring (2)
This commit is contained in:
parent
2ebc3afc7c
commit
2f78c39d9c
142
BlockDecoder.cpp
Normal file
142
BlockDecoder.cpp
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
#include <string>
|
||||||
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
#include "BlockDecoder.h"
|
||||||
|
#include "ZlibDecompressor.h"
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
if (version >= 24) {
|
||||||
|
size_t index = datapos << 1;
|
||||||
|
return (mapData[index] << 8) | mapData[index + 1];
|
||||||
|
} else if (version >= 20) {
|
||||||
|
if (mapData[datapos] <= 0x80)
|
||||||
|
return mapData[datapos];
|
||||||
|
else
|
||||||
|
return (int(mapData[datapos]) << 4) | (int(mapData[datapos + 0x2000]) >> 4);
|
||||||
|
}
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "Unsupported map version " << version;
|
||||||
|
throw std::runtime_error(oss.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
BlockDecoder::BlockDecoder()
|
||||||
|
{
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BlockDecoder::reset()
|
||||||
|
{
|
||||||
|
m_blockAirId = -1;
|
||||||
|
m_blockIgnoreId = -1;
|
||||||
|
m_nameMap.clear();
|
||||||
|
|
||||||
|
m_version = 0;
|
||||||
|
m_mapData = ustring();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BlockDecoder::decode(const ustring &datastr)
|
||||||
|
{
|
||||||
|
const unsigned char *data = datastr.c_str();
|
||||||
|
size_t length = datastr.length();
|
||||||
|
// TODO: bounds checks
|
||||||
|
|
||||||
|
uint8_t version = data[0];
|
||||||
|
//uint8_t flags = data[1];
|
||||||
|
m_version = version;
|
||||||
|
|
||||||
|
size_t dataOffset = 0;
|
||||||
|
if (version >= 27)
|
||||||
|
dataOffset = 6;
|
||||||
|
else if (version >= 22)
|
||||||
|
dataOffset = 4;
|
||||||
|
else
|
||||||
|
dataOffset = 2;
|
||||||
|
|
||||||
|
ZlibDecompressor decompressor(data, length);
|
||||||
|
decompressor.setSeekPos(dataOffset);
|
||||||
|
m_mapData = decompressor.decompress();
|
||||||
|
decompressor.decompress(); // unused metadata
|
||||||
|
dataOffset = decompressor.seekPos();
|
||||||
|
|
||||||
|
// Skip unused data
|
||||||
|
if (version <= 21)
|
||||||
|
dataOffset += 2;
|
||||||
|
if (version == 23)
|
||||||
|
dataOffset += 1;
|
||||||
|
if (version == 24) {
|
||||||
|
uint8_t ver = data[dataOffset++];
|
||||||
|
if (ver == 1) {
|
||||||
|
uint16_t num = readU16(data + dataOffset);
|
||||||
|
dataOffset += 2;
|
||||||
|
dataOffset += 10 * num;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip unused static objects
|
||||||
|
dataOffset++; // Skip static object version
|
||||||
|
int staticObjectCount = readU16(data + dataOffset);
|
||||||
|
dataOffset += 2;
|
||||||
|
for (int i = 0; i < staticObjectCount; ++i) {
|
||||||
|
dataOffset += 13;
|
||||||
|
uint16_t dataSize = readU16(data + dataOffset);
|
||||||
|
dataOffset += dataSize + 2;
|
||||||
|
}
|
||||||
|
dataOffset += 4; // Skip timestamp
|
||||||
|
|
||||||
|
// Read mapping
|
||||||
|
if (version >= 22) {
|
||||||
|
dataOffset++; // mapping version
|
||||||
|
uint16_t numMappings = readU16(data + dataOffset);
|
||||||
|
dataOffset += 2;
|
||||||
|
for (int i = 0; i < numMappings; ++i) {
|
||||||
|
uint16_t nodeId = readU16(data + dataOffset);
|
||||||
|
dataOffset += 2;
|
||||||
|
uint16_t nameLen = readU16(data + dataOffset);
|
||||||
|
dataOffset += 2;
|
||||||
|
std::string name(reinterpret_cast<const char *>(data) + dataOffset, nameLen);
|
||||||
|
if (name == "air")
|
||||||
|
m_blockAirId = nodeId;
|
||||||
|
else if (name == "ignore")
|
||||||
|
m_blockIgnoreId = nodeId;
|
||||||
|
else
|
||||||
|
m_nameMap[nodeId] = name;
|
||||||
|
dataOffset += nameLen;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Node timers
|
||||||
|
if (version >= 25) {
|
||||||
|
dataOffset++;
|
||||||
|
uint16_t numTimers = readU16(data + dataOffset);
|
||||||
|
dataOffset += 2;
|
||||||
|
dataOffset += numTimers * 10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BlockDecoder::isEmpty() const
|
||||||
|
{
|
||||||
|
// only contains ignore and air nodes?
|
||||||
|
return m_nameMap.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
if (content == m_blockAirId || content == m_blockIgnoreId)
|
||||||
|
return "";
|
||||||
|
NameMap::const_iterator it = m_nameMap.find(content);
|
||||||
|
if (it == m_nameMap.end()) {
|
||||||
|
std::cerr << "Skipping node with invalid ID." << std::endl;
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return it->second;
|
||||||
|
}
|
@ -173,6 +173,7 @@ configure_file(
|
|||||||
add_definitions ( -DUSE_CMAKE_CONFIG_H )
|
add_definitions ( -DUSE_CMAKE_CONFIG_H )
|
||||||
|
|
||||||
set(mapper_SRCS
|
set(mapper_SRCS
|
||||||
|
BlockDecoder.cpp
|
||||||
PixelAttributes.cpp
|
PixelAttributes.cpp
|
||||||
PlayerAttributes.cpp
|
PlayerAttributes.cpp
|
||||||
TileGenerator.cpp
|
TileGenerator.cpp
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstdlib>
|
|
||||||
#include <climits>
|
#include <climits>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
@ -7,10 +6,11 @@
|
|||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "TileGenerator.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "PlayerAttributes.h"
|
#include "PlayerAttributes.h"
|
||||||
#include "TileGenerator.h"
|
#include "BlockDecoder.h"
|
||||||
#include "ZlibDecompressor.h"
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "db-sqlite3.h"
|
#include "db-sqlite3.h"
|
||||||
#if USE_POSTGRESQL
|
#if USE_POSTGRESQL
|
||||||
@ -25,11 +25,6 @@
|
|||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
static inline uint16_t readU16(const unsigned char *data)
|
|
||||||
{
|
|
||||||
return data[0] << 8 | data[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static inline T mymax(T a, T b)
|
static inline T mymax(T a, T b)
|
||||||
{
|
{
|
||||||
@ -54,22 +49,6 @@ static int round_multiple_nosign(int n, int f)
|
|||||||
return sign * (abs_n + f - (abs_n % f));
|
return sign * (abs_n + f - (abs_n % f));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int readBlockContent(const unsigned char *mapData, int version, int datapos)
|
|
||||||
{
|
|
||||||
if (version >= 24) {
|
|
||||||
size_t index = datapos << 1;
|
|
||||||
return (mapData[index] << 8) | mapData[index + 1];
|
|
||||||
} else if (version >= 20) {
|
|
||||||
if (mapData[datapos] <= 0x80)
|
|
||||||
return mapData[datapos];
|
|
||||||
else
|
|
||||||
return (int(mapData[datapos]) << 4) | (int(mapData[datapos + 0x2000]) >> 4);
|
|
||||||
}
|
|
||||||
std::ostringstream oss;
|
|
||||||
oss << "Unsupported map version " << version;
|
|
||||||
throw std::runtime_error(oss.str());
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline unsigned int colorSafeBounds (int channel)
|
static inline unsigned int colorSafeBounds (int channel)
|
||||||
{
|
{
|
||||||
return mymin(mymax(channel, 0), 255);
|
return mymin(mymax(channel, 0), 255);
|
||||||
@ -373,6 +352,7 @@ void TileGenerator::createImage()
|
|||||||
|
|
||||||
void TileGenerator::renderMap()
|
void TileGenerator::renderMap()
|
||||||
{
|
{
|
||||||
|
BlockDecoder blk;
|
||||||
std::list<int> zlist = getZValueList();
|
std::list<int> zlist = getZValueList();
|
||||||
for (std::list<int>::iterator zPosition = zlist.begin(); zPosition != zlist.end(); ++zPosition) {
|
for (std::list<int>::iterator zPosition = zlist.begin(); zPosition != zlist.end(); ++zPosition) {
|
||||||
int zPos = *zPosition;
|
int zPos = *zPosition;
|
||||||
@ -399,87 +379,12 @@ void TileGenerator::renderMap()
|
|||||||
const BlockList &blockStack = blocks[xPos];
|
const BlockList &blockStack = blocks[xPos];
|
||||||
for (BlockList::const_iterator it = blockStack.begin(); it != blockStack.end(); ++it) {
|
for (BlockList::const_iterator it = blockStack.begin(); it != blockStack.end(); ++it) {
|
||||||
const BlockPos &pos = it->first;
|
const BlockPos &pos = it->first;
|
||||||
const unsigned char *data = it->second.c_str();
|
|
||||||
size_t length = it->second.length();
|
|
||||||
|
|
||||||
uint8_t version = data[0];
|
blk.reset();
|
||||||
//uint8_t flags = data[1];
|
blk.decode(it->second);
|
||||||
|
if (blk.isEmpty())
|
||||||
size_t dataOffset = 0;
|
|
||||||
if (version >= 27)
|
|
||||||
dataOffset = 6;
|
|
||||||
else if (version >= 22)
|
|
||||||
dataOffset = 4;
|
|
||||||
else
|
|
||||||
dataOffset = 2;
|
|
||||||
|
|
||||||
ZlibDecompressor decompressor(data, length);
|
|
||||||
decompressor.setSeekPos(dataOffset);
|
|
||||||
ustring mapData = decompressor.decompress();
|
|
||||||
ustring mapMetadata = decompressor.decompress();
|
|
||||||
dataOffset = decompressor.seekPos();
|
|
||||||
|
|
||||||
// Skip unused data
|
|
||||||
if (version <= 21)
|
|
||||||
dataOffset += 2;
|
|
||||||
if (version == 23)
|
|
||||||
dataOffset += 1;
|
|
||||||
if (version == 24) {
|
|
||||||
uint8_t ver = data[dataOffset++];
|
|
||||||
if (ver == 1) {
|
|
||||||
uint16_t num = readU16(data + dataOffset);
|
|
||||||
dataOffset += 2;
|
|
||||||
dataOffset += 10 * num;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Skip unused static objects
|
|
||||||
dataOffset++; // Skip static object version
|
|
||||||
int staticObjectCount = readU16(data + dataOffset);
|
|
||||||
dataOffset += 2;
|
|
||||||
for (int i = 0; i < staticObjectCount; ++i) {
|
|
||||||
dataOffset += 13;
|
|
||||||
uint16_t dataSize = readU16(data + dataOffset);
|
|
||||||
dataOffset += dataSize + 2;
|
|
||||||
}
|
|
||||||
dataOffset += 4; // Skip timestamp
|
|
||||||
|
|
||||||
m_blockAirId = -1;
|
|
||||||
m_blockIgnoreId = -1;
|
|
||||||
m_nameMap.clear();
|
|
||||||
// Read mapping
|
|
||||||
if (version >= 22) {
|
|
||||||
dataOffset++; // mapping version
|
|
||||||
uint16_t numMappings = readU16(data + dataOffset);
|
|
||||||
dataOffset += 2;
|
|
||||||
for (int i = 0; i < numMappings; ++i) {
|
|
||||||
uint16_t nodeId = readU16(data + dataOffset);
|
|
||||||
dataOffset += 2;
|
|
||||||
uint16_t nameLen = readU16(data + dataOffset);
|
|
||||||
dataOffset += 2;
|
|
||||||
string name = string(reinterpret_cast<const char *>(data) + dataOffset, nameLen);
|
|
||||||
if (name == "air")
|
|
||||||
m_blockAirId = nodeId;
|
|
||||||
else if (name == "ignore")
|
|
||||||
m_blockIgnoreId = nodeId;
|
|
||||||
else
|
|
||||||
m_nameMap[nodeId] = name;
|
|
||||||
dataOffset += nameLen;
|
|
||||||
}
|
|
||||||
// Skip block if made of only air or ignore nodes
|
|
||||||
if (m_nameMap.empty())
|
|
||||||
continue;
|
continue;
|
||||||
}
|
renderMapBlock(blk, pos);
|
||||||
|
|
||||||
// Node timers
|
|
||||||
if (version >= 25) {
|
|
||||||
dataOffset++;
|
|
||||||
uint16_t numTimers = readU16(data + dataOffset);
|
|
||||||
dataOffset += 2;
|
|
||||||
dataOffset += numTimers * 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
renderMapBlock(mapData, pos, version);
|
|
||||||
|
|
||||||
bool allRead = true;
|
bool allRead = true;
|
||||||
for (int i = 0; i < 16; ++i) {
|
for (int i = 0; i < 16; ++i) {
|
||||||
@ -502,11 +407,10 @@ void TileGenerator::renderMap()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TileGenerator::renderMapBlock(const ustring &mapBlock, const BlockPos &pos, int version)
|
void TileGenerator::renderMapBlock(const BlockDecoder &blk, const BlockPos &pos)
|
||||||
{
|
{
|
||||||
int xBegin = (pos.x - m_xMin) * 16;
|
int xBegin = (pos.x - m_xMin) * 16;
|
||||||
int zBegin = (m_zMax - pos.z) * 16;
|
int zBegin = (m_zMax - pos.z) * 16;
|
||||||
const unsigned char *mapData = mapBlock.c_str();
|
|
||||||
int minY = (pos.y * 16 > m_yMin) ? 0 : m_yMin - pos.y * 16;
|
int minY = (pos.y * 16 > m_yMin) ? 0 : m_yMin - pos.y * 16;
|
||||||
int maxY = (pos.y * 16 < m_yMax) ? 15 : m_yMax - pos.y * 16;
|
int maxY = (pos.y * 16 < m_yMax) ? 15 : m_yMax - pos.y * 16;
|
||||||
for (int z = 0; z < 16; ++z) {
|
for (int z = 0; z < 16; ++z) {
|
||||||
@ -517,16 +421,9 @@ void TileGenerator::renderMapBlock(const ustring &mapBlock, const BlockPos &pos,
|
|||||||
int imageX = xBegin + x;
|
int imageX = xBegin + x;
|
||||||
|
|
||||||
for (int y = maxY; y >= minY; --y) {
|
for (int y = maxY; y >= minY; --y) {
|
||||||
int position = x + (y << 4) + (z << 8);
|
string name = blk.getNode(x, y, z);
|
||||||
int content = readBlockContent(mapData, version, position);
|
if (name == "")
|
||||||
if (content == m_blockAirId || content == m_blockIgnoreId)
|
|
||||||
continue;
|
continue;
|
||||||
NameMap::iterator blockName = m_nameMap.find(content);
|
|
||||||
if (blockName == m_nameMap.end()) {
|
|
||||||
std::cerr << "Skipping node with invalid ID." << std::endl;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const string &name = blockName->second;
|
|
||||||
ColorMap::const_iterator color = m_colorMap.find(name);
|
ColorMap::const_iterator color = m_colorMap.find(name);
|
||||||
if (color != m_colorMap.end()) {
|
if (color != m_colorMap.end()) {
|
||||||
const Color c = color->second.to_color();
|
const Color c = color->second.to_color();
|
||||||
|
35
include/BlockDecoder.h
Normal file
35
include/BlockDecoder.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#ifndef BLOCKDECODER_H
|
||||||
|
#define BLOCKDECODER_H
|
||||||
|
|
||||||
|
#if __cplusplus >= 201103L
|
||||||
|
#include <unordered_map>
|
||||||
|
#else
|
||||||
|
#include <map>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
|
class BlockDecoder {
|
||||||
|
public:
|
||||||
|
BlockDecoder();
|
||||||
|
|
||||||
|
void reset();
|
||||||
|
void decode(const ustring &data);
|
||||||
|
bool isEmpty() const;
|
||||||
|
std::string getNode(u8 x, u8 y, u8 z) const; // returns "" for air, ignore and invalid nodes
|
||||||
|
|
||||||
|
private:
|
||||||
|
#if __cplusplus >= 201103L
|
||||||
|
typedef std::unordered_map<int, std::string> NameMap;
|
||||||
|
#else
|
||||||
|
typedef std::map<int, std::string> NameMap;
|
||||||
|
#endif
|
||||||
|
NameMap m_nameMap;
|
||||||
|
int m_blockAirId;
|
||||||
|
int m_blockIgnoreId;
|
||||||
|
|
||||||
|
u8 m_version;
|
||||||
|
ustring m_mapData;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // BLOCKDECODER_H
|
@ -14,7 +14,9 @@
|
|||||||
#endif
|
#endif
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "PixelAttributes.h"
|
#include "PixelAttributes.h"
|
||||||
|
#include "BlockDecoder.h"
|
||||||
#include "Image.h"
|
#include "Image.h"
|
||||||
#include "db.h"
|
#include "db.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
@ -43,11 +45,9 @@ class TileGenerator
|
|||||||
private:
|
private:
|
||||||
#if __cplusplus >= 201103L
|
#if __cplusplus >= 201103L
|
||||||
typedef std::unordered_map<std::string, ColorEntry> ColorMap;
|
typedef std::unordered_map<std::string, ColorEntry> ColorMap;
|
||||||
typedef std::unordered_map<int, std::string> NameMap;
|
|
||||||
typedef std::unordered_set<std::string> NameSet;
|
typedef std::unordered_set<std::string> NameSet;
|
||||||
#else
|
#else
|
||||||
typedef std::map<std::string, ColorEntry> ColorMap;
|
typedef std::map<std::string, ColorEntry> ColorMap;
|
||||||
typedef std::map<int, std::string> NameMap;
|
|
||||||
typedef std::set<std::string> NameSet;
|
typedef std::set<std::string> NameSet;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -80,7 +80,7 @@ private:
|
|||||||
void createImage();
|
void createImage();
|
||||||
void renderMap();
|
void renderMap();
|
||||||
std::list<int> getZValueList() const;
|
std::list<int> getZValueList() const;
|
||||||
void renderMapBlock(const ustring &mapBlock, const BlockPos &pos, int version);
|
void renderMapBlock(const BlockDecoder &blk, const BlockPos &pos);
|
||||||
void renderMapBlockBottom(const BlockPos &pos);
|
void renderMapBlockBottom(const BlockPos &pos);
|
||||||
void renderShading(int zPos);
|
void renderShading(int zPos);
|
||||||
void renderScale();
|
void renderScale();
|
||||||
@ -121,7 +121,6 @@ private:
|
|||||||
int m_mapWidth;
|
int m_mapWidth;
|
||||||
int m_mapHeight;
|
int m_mapHeight;
|
||||||
std::list<std::pair<int, int> > m_positions;
|
std::list<std::pair<int, int> > m_positions;
|
||||||
NameMap m_nameMap;
|
|
||||||
ColorMap m_colorMap;
|
ColorMap m_colorMap;
|
||||||
uint16_t m_readPixels[16];
|
uint16_t m_readPixels[16];
|
||||||
uint16_t m_readInfo[16];
|
uint16_t m_readInfo[16];
|
||||||
@ -129,8 +128,6 @@ private:
|
|||||||
Color m_color[16][16];
|
Color m_color[16][16];
|
||||||
uint8_t m_thickness[16][16];
|
uint8_t m_thickness[16][16];
|
||||||
|
|
||||||
int m_blockAirId;
|
|
||||||
int m_blockIgnoreId;
|
|
||||||
int m_zoom;
|
int m_zoom;
|
||||||
uint m_scales;
|
uint m_scales;
|
||||||
}; // class TileGenerator
|
}; // class TileGenerator
|
||||||
|
Loading…
Reference in New Issue
Block a user