Freeminer database coordinate format support ('a<x>,<y>,<z>')
This commit is contained in:
parent
0a9a885e63
commit
66122c1c2e
101
BlockPos.h
101
BlockPos.h
@ -5,8 +5,23 @@
|
|||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <climits>
|
#include <climits>
|
||||||
|
#include <cctype>
|
||||||
|
#include <string>
|
||||||
|
#include <sstream>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
struct BlockPos {
|
struct BlockPos {
|
||||||
|
// m_strFormat is used to record the original format that was obtained
|
||||||
|
// from the database (and thus, the format to use when querying
|
||||||
|
// the database again). DO NOT USE M_STRfORMAT FOR ANYTHING ELSE.
|
||||||
|
// Use the argument to databasePosStrFmt to force a specific display format.
|
||||||
|
enum StrFormat {
|
||||||
|
Unknown = 0,
|
||||||
|
I64, // Minetest & Freeminer
|
||||||
|
XYZ,
|
||||||
|
AXYZ, // Freeminer
|
||||||
|
};
|
||||||
int dimension[3];
|
int dimension[3];
|
||||||
// Unfortunately, static member references are not supported (even though static member pointers are...)
|
// Unfortunately, static member references are not supported (even though static member pointers are...)
|
||||||
// I'd like to have:
|
// I'd like to have:
|
||||||
@ -16,20 +31,24 @@ struct BlockPos {
|
|||||||
int &y = dimension[1];
|
int &y = dimension[1];
|
||||||
int &z = dimension[2];
|
int &z = dimension[2];
|
||||||
//#if SIZE_MAX > (1LL << 36)
|
//#if SIZE_MAX > (1LL << 36)
|
||||||
// std::size_t hash(void) const { return databasePos(); }
|
// std::size_t hash(void) const { return databasePosI64(); }
|
||||||
//#else
|
//#else
|
||||||
// std::size_t hash(void) const { return databasePos() % SIZE_MAX; }
|
// std::size_t hash(void) const { return databasePosI64() % SIZE_MAX; }
|
||||||
//#endif
|
//#endif
|
||||||
BlockPos() : dimension{0, 0, 0} {}
|
BlockPos() : dimension{0, 0, 0}, m_strFormat(Unknown) {}
|
||||||
BlockPos(int _x, int _y, int _z) : dimension{_x, _y, _z} {}
|
BlockPos(int _x, int _y, int _z) : dimension{_x, _y, _z}, m_strFormat(Unknown) {}
|
||||||
BlockPos(const BlockPos &pos) : dimension{pos.x, pos.y, pos.z} {}
|
BlockPos(const BlockPos &pos) : dimension{pos.x, pos.y, pos.z}, m_strFormat(pos.m_strFormat) {}
|
||||||
BlockPos(int64_t i) { setFromDBPos(i); }
|
BlockPos(int64_t i) { operator=(i); }
|
||||||
int64_t databasePos(void) const { return getDBPos(); }
|
BlockPos(const std::string &s) { operator=(s); }
|
||||||
|
int64_t databasePosI64(void) const { return getDBPos(); }
|
||||||
|
std::string databasePosStr(StrFormat defaultFormat = Unknown) const;
|
||||||
|
std::string databasePosStrFmt(StrFormat format) const;
|
||||||
|
|
||||||
bool operator<(const BlockPos& p) const;
|
bool operator<(const BlockPos& p) const;
|
||||||
bool operator==(const BlockPos& p) const;
|
bool operator==(const BlockPos& p) const;
|
||||||
void operator=(const BlockPos &p) { x = p.x; y = p.y; z = p.z; }
|
void operator=(const BlockPos &p) { x = p.x; y = p.y; z = p.z; m_strFormat = p.m_strFormat; }
|
||||||
void operator=(int64_t i) { setFromDBPos(i); }
|
void operator=(int64_t i) { setFromDBPos(i); m_strFormat = I64; }
|
||||||
|
void operator=(const std::string &s);
|
||||||
|
|
||||||
static const int Any = INT_MIN;
|
static const int Any = INT_MIN;
|
||||||
static const int Invalid = INT_MAX;
|
static const int Invalid = INT_MAX;
|
||||||
@ -41,6 +60,10 @@ protected:
|
|||||||
// int64_t getDBPos(void) const;
|
// int64_t getDBPos(void) const;
|
||||||
#include "minetest-database.h"
|
#include "minetest-database.h"
|
||||||
|
|
||||||
|
private:
|
||||||
|
// WARNING: see comment about m_strFormat above !!
|
||||||
|
StrFormat m_strFormat;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NodeCoord : BlockPos
|
struct NodeCoord : BlockPos
|
||||||
@ -91,6 +114,66 @@ namespace std {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void BlockPos::operator=(const std::string &s)
|
||||||
|
{
|
||||||
|
std::istringstream is(s);
|
||||||
|
if (isdigit(is.peek()) || is.peek() == '-' || is.peek() == '+') {
|
||||||
|
int64_t ipos;
|
||||||
|
is >> ipos;
|
||||||
|
if (is.bad() || !is.eof()) {
|
||||||
|
throw std::runtime_error(std::string("Failed to decode i64 (minetest) coordinate string from database (") + s + ")" );
|
||||||
|
}
|
||||||
|
operator=(ipos);
|
||||||
|
m_strFormat = I64;
|
||||||
|
}
|
||||||
|
else if (is.peek() == 'a') {
|
||||||
|
// Freeminer new format (a<x>,<y>,<z>)
|
||||||
|
char c1, c2;
|
||||||
|
is >> c1;
|
||||||
|
is >> x;
|
||||||
|
is >> c1;
|
||||||
|
is >> y;
|
||||||
|
is >> c2;
|
||||||
|
is >> z;
|
||||||
|
if (is.bad() || !is.eof() || c1 != ',' || c2 != ',') {
|
||||||
|
throw std::runtime_error(std::string("Failed to decode axyz (freeminer) coordinate string from database (") + s + ")" );
|
||||||
|
}
|
||||||
|
m_strFormat = AXYZ;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw std::runtime_error(std::string("Failed to detect format of coordinate string from database (") + s + ")" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::string BlockPos::databasePosStr(StrFormat defaultFormat) const
|
||||||
|
{
|
||||||
|
StrFormat format = m_strFormat;
|
||||||
|
if (format == Unknown)
|
||||||
|
format = defaultFormat;
|
||||||
|
return databasePosStrFmt(format);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline std::string BlockPos::databasePosStrFmt(StrFormat format) const
|
||||||
|
{
|
||||||
|
std::ostringstream os;
|
||||||
|
switch(format) {
|
||||||
|
case Unknown:
|
||||||
|
throw std::runtime_error(std::string("Internal error: Converting BlockPos to unknown string type"));
|
||||||
|
break;
|
||||||
|
case I64:
|
||||||
|
os << databasePosI64();
|
||||||
|
break;
|
||||||
|
case XYZ:
|
||||||
|
os << x << ',' << y << ',' << z;
|
||||||
|
break;
|
||||||
|
case AXYZ:
|
||||||
|
os << 'a' << x << ',' << y << ',' << z;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return os.str();
|
||||||
|
}
|
||||||
|
|
||||||
// operator< should order the positions in the
|
// operator< should order the positions in the
|
||||||
// order the corresponding pixels are generated:
|
// order the corresponding pixels are generated:
|
||||||
// First (most significant): z coordinate, descending (i.e. reversed)
|
// First (most significant): z coordinate, descending (i.e. reversed)
|
||||||
|
@ -636,7 +636,7 @@ void TileGenerator::loadBlocks()
|
|||||||
map_blocks = 0;
|
map_blocks = 0;
|
||||||
for(DB::BlockPosList::const_iterator it = blocks.begin(); it != blocks.end(); ++it) {
|
for(DB::BlockPosList::const_iterator it = blocks.begin(); it != blocks.end(); ++it) {
|
||||||
world_blocks ++;
|
world_blocks ++;
|
||||||
BlockPos pos = *it;
|
const BlockPos &pos = *it;
|
||||||
if (pos.x < mapXMin) {
|
if (pos.x < mapXMin) {
|
||||||
mapXMin = pos.x;
|
mapXMin = pos.x;
|
||||||
}
|
}
|
||||||
@ -790,17 +790,6 @@ void TileGenerator::loadBlocks()
|
|||||||
#undef MESSAGE_WIDTH
|
#undef MESSAGE_WIDTH
|
||||||
}
|
}
|
||||||
|
|
||||||
inline BlockPos TileGenerator::decodeBlockPos(int64_t blockId) const
|
|
||||||
{
|
|
||||||
BlockPos pos;
|
|
||||||
pos.x = unsignedToSigned(pythonmodulo(blockId, 4096), 2048);
|
|
||||||
blockId = (blockId - pos.x) / 4096;
|
|
||||||
pos.y = unsignedToSigned(pythonmodulo(blockId, 4096), 2048);
|
|
||||||
blockId = (blockId - pos.y) / 4096;
|
|
||||||
pos.z = unsignedToSigned(pythonmodulo(blockId, 4096), 2048);
|
|
||||||
return pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TileGenerator::pushPixelRows(int zPosLimit) {
|
void TileGenerator::pushPixelRows(int zPosLimit) {
|
||||||
if (m_shading)
|
if (m_shading)
|
||||||
m_blockPixelAttributes.renderShading(m_drawAlpha);
|
m_blockPixelAttributes.renderShading(m_drawAlpha);
|
||||||
@ -1175,7 +1164,7 @@ void TileGenerator::renderMap()
|
|||||||
}
|
}
|
||||||
catch (UnpackError &e) {
|
catch (UnpackError &e) {
|
||||||
std::cerr << "Failed to unpack map block " << pos.x << "," << pos.y << "," << pos.z
|
std::cerr << "Failed to unpack map block " << pos.x << "," << pos.y << "," << pos.z
|
||||||
<< " (id: " << pos.databasePos() << "). Block corrupt ?"
|
<< " (id: " << pos.databasePosStr(BlockPos::I64) << "). Block corrupt ?"
|
||||||
<< std::endl
|
<< std::endl
|
||||||
<< "\tCoordinates: " << pos.x*16 << "," << pos.y*16 << "," << pos.z*16 << "+16+16+16"
|
<< "\tCoordinates: " << pos.x*16 << "," << pos.y*16 << "," << pos.z*16 << "+16+16+16"
|
||||||
<< "; Data: " << e.type << " at: " << e.offset << "(+" << e.length << ")/" << e.dataLength
|
<< "; Data: " << e.type << " at: " << e.offset << "(+" << e.length << ")/" << e.dataLength
|
||||||
@ -1184,7 +1173,7 @@ void TileGenerator::renderMap()
|
|||||||
}
|
}
|
||||||
catch (ZlibDecompressor::DecompressError &e) {
|
catch (ZlibDecompressor::DecompressError &e) {
|
||||||
std::cerr << "Failed to decompress data in map block " << pos.x << "," << pos.y << "," << pos.z
|
std::cerr << "Failed to decompress data in map block " << pos.x << "," << pos.y << "," << pos.z
|
||||||
<< " (id: " << pos.databasePos() << "). Block corrupt ?"
|
<< " (id: " << pos.databasePosStr(BlockPos::I64) << "). Block corrupt ?"
|
||||||
<< std::endl
|
<< std::endl
|
||||||
<< "\tCoordinates: " << pos.x*16 << "," << pos.y*16 << "," << pos.z*16 << "+16+16+16"
|
<< "\tCoordinates: " << pos.x*16 << "," << pos.y*16 << "," << pos.z*16 << "+16+16+16"
|
||||||
<< "; Cause: " << e.message
|
<< "; Cause: " << e.message
|
||||||
|
@ -116,7 +116,6 @@ private:
|
|||||||
std::string getWorldDatabaseBackend(const std::string &input);
|
std::string getWorldDatabaseBackend(const std::string &input);
|
||||||
void openDb(const std::string &input);
|
void openDb(const std::string &input);
|
||||||
void loadBlocks();
|
void loadBlocks();
|
||||||
BlockPos decodeBlockPos(int64_t blockId) const;
|
|
||||||
void createImage();
|
void createImage();
|
||||||
void computeMapParameters();
|
void computeMapParameters();
|
||||||
void computeTileParameters(
|
void computeTileParameters(
|
||||||
|
@ -50,7 +50,7 @@ const DB::BlockPosList &DBLevelDB::getBlockPos() {
|
|||||||
m_blockPosList.clear();
|
m_blockPosList.clear();
|
||||||
leveldb::Iterator* it = m_db->NewIterator(leveldb::ReadOptions());
|
leveldb::Iterator* it = m_db->NewIterator(leveldb::ReadOptions());
|
||||||
for (it->SeekToFirst(); it->Valid(); it->Next()) {
|
for (it->SeekToFirst(); it->Valid(); it->Next()) {
|
||||||
m_blockPosList.push_back(stoi64(it->key().ToString()));
|
m_blockPosList.push_back(BlockPos(it->key().ToString()));
|
||||||
}
|
}
|
||||||
delete it;
|
delete it;
|
||||||
return m_blockPosList;
|
return m_blockPosList;
|
||||||
@ -63,7 +63,7 @@ DB::Block DBLevelDB::getBlockOnPos(const BlockPos &pos)
|
|||||||
|
|
||||||
m_blocksReadCount++;
|
m_blocksReadCount++;
|
||||||
|
|
||||||
status = m_db->Get(leveldb::ReadOptions(), i64tos(pos.databasePos()), &datastr);
|
status = m_db->Get(leveldb::ReadOptions(), pos.databasePosStr(), &datastr);
|
||||||
if(status.ok()) {
|
if(status.ok()) {
|
||||||
m_blocksUnCachedCount++;
|
m_blocksUnCachedCount++;
|
||||||
return Block(pos, ustring(reinterpret_cast<const unsigned char *>(datastr.c_str()), datastr.size()));
|
return Block(pos, ustring(reinterpret_cast<const unsigned char *>(datastr.c_str()), datastr.size()));
|
||||||
|
@ -148,7 +148,7 @@ const DB::BlockPosList &DBRedis::getBlockPos()
|
|||||||
for(size_t i = 0; i < reply->elements; i++) {
|
for(size_t i = 0; i < reply->elements; i++) {
|
||||||
if(reply->element[i]->type != REDIS_REPLY_STRING)
|
if(reply->element[i]->type != REDIS_REPLY_STRING)
|
||||||
throw std::runtime_error("Got wrong response to 'HKEYS %s' command");
|
throw std::runtime_error("Got wrong response to 'HKEYS %s' command");
|
||||||
m_blockPosList.push_back(stoi64(reply->element[i]->str));
|
m_blockPosList.push_back(BlockPos(reply->element[i]->str));
|
||||||
}
|
}
|
||||||
|
|
||||||
freeReplyObject(reply);
|
freeReplyObject(reply);
|
||||||
@ -164,8 +164,7 @@ DB::Block DBRedis::getBlockOnPos(const BlockPos &pos)
|
|||||||
|
|
||||||
m_blocksReadCount++;
|
m_blocksReadCount++;
|
||||||
|
|
||||||
tmp = i64tos(pos.databasePos());
|
reply = (redisReply*) redisCommand(ctx, "HGET %s %s", hash.c_str(), pos.databasePosStr().c_str());
|
||||||
reply = (redisReply*) redisCommand(ctx, "HGET %s %s", hash.c_str(), tmp.c_str());
|
|
||||||
if(!reply)
|
if(!reply)
|
||||||
throw std::runtime_error(std::string("redis command 'HGET %s %s' failed: ") + ctx->errstr);
|
throw std::runtime_error(std::string("redis command 'HGET %s %s' failed: ") + ctx->errstr);
|
||||||
if (reply->type == REDIS_REPLY_STRING && reply->len != 0) {
|
if (reply->type == REDIS_REPLY_STRING && reply->len != 0) {
|
||||||
|
@ -105,7 +105,7 @@ DB::Block DBSQLite3::getBlockOnPosRaw(const BlockPos &pos)
|
|||||||
Block block(pos,reinterpret_cast<const unsigned char *>(""));
|
Block block(pos,reinterpret_cast<const unsigned char *>(""));
|
||||||
int result = 0;
|
int result = 0;
|
||||||
|
|
||||||
sqlite3_bind_int64(m_blockOnPosStatement, 1, pos.databasePos());
|
sqlite3_bind_int64(m_blockOnPosStatement, 1, pos.databasePosI64());
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
result = sqlite3_step(m_blockOnPosStatement);
|
result = sqlite3_step(m_blockOnPosStatement);
|
||||||
@ -151,12 +151,12 @@ DB::Block DBSQLite3::getBlockOnPos(const BlockPos &pos)
|
|||||||
m_blocksReadCount++;
|
m_blocksReadCount++;
|
||||||
|
|
||||||
BlockCache::const_iterator DBBlockSearch;
|
BlockCache::const_iterator DBBlockSearch;
|
||||||
DBBlockSearch = m_blockCache.find(pos.databasePos());
|
DBBlockSearch = m_blockCache.find(pos.databasePosI64());
|
||||||
if (DBBlockSearch == m_blockCache.end()) {
|
if (DBBlockSearch == m_blockCache.end()) {
|
||||||
if (cacheWorldRow) {
|
if (cacheWorldRow) {
|
||||||
m_blockCache.clear();
|
m_blockCache.clear();
|
||||||
cacheBlocksOnZRaw(pos.z);
|
cacheBlocksOnZRaw(pos.z);
|
||||||
DBBlockSearch = m_blockCache.find(pos.databasePos());
|
DBBlockSearch = m_blockCache.find(pos.databasePosI64());
|
||||||
if (DBBlockSearch != m_blockCache.end()) {
|
if (DBBlockSearch != m_blockCache.end()) {
|
||||||
return Block(pos, DBBlockSearch->second);
|
return Block(pos, DBBlockSearch->second);
|
||||||
}
|
}
|
||||||
|
2
db.h
2
db.h
@ -13,7 +13,7 @@
|
|||||||
class DB {
|
class DB {
|
||||||
public:
|
public:
|
||||||
typedef std::pair<BlockPos, ustring> Block;
|
typedef std::pair<BlockPos, ustring> Block;
|
||||||
typedef std::vector<int64_t> BlockPosList;
|
typedef std::vector<BlockPos> BlockPosList;
|
||||||
virtual const BlockPosList &getBlockPos()=0;
|
virtual const BlockPosList &getBlockPos()=0;
|
||||||
virtual int getBlocksUnCachedCount(void)=0;
|
virtual int getBlocksUnCachedCount(void)=0;
|
||||||
virtual int getBlocksCachedCount(void)=0;
|
virtual int getBlocksCachedCount(void)=0;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user