Add --dumpblock flag for advanced use

This is not only useful for debugging minetestmapper itself but
also makes it a standalone tool for extracting data you want to work on
from a Minetest map.
This commit is contained in:
sfan5 2022-02-09 21:52:28 +01:00
parent 2e353312b5
commit b491dd375a
5 changed files with 56 additions and 13 deletions

View File

@ -254,6 +254,11 @@ void TileGenerator::setExhaustiveSearch(int mode)
m_exhaustiveSearch = mode; m_exhaustiveSearch = mode;
} }
void TileGenerator::setDontWriteEmpty(bool f)
{
m_dontWriteEmpty = f;
}
void TileGenerator::parseColorsFile(const std::string &fileName) void TileGenerator::parseColorsFile(const std::string &fileName)
{ {
std::ifstream in(fileName); std::ifstream in(fileName);
@ -265,9 +270,8 @@ void TileGenerator::parseColorsFile(const std::string &fileName)
void TileGenerator::printGeometry(const std::string &input) void TileGenerator::printGeometry(const std::string &input)
{ {
std::string input_path = input; std::string input_path = input;
if (input_path[input.length() - 1] != PATH_SEPARATOR) { if (input_path.back() != PATH_SEPARATOR)
input_path += PATH_SEPARATOR; input_path += PATH_SEPARATOR;
}
setExhaustiveSearch(EXH_NEVER); setExhaustiveSearch(EXH_NEVER);
openDb(input_path); openDb(input_path);
@ -283,17 +287,33 @@ void TileGenerator::printGeometry(const std::string &input)
} }
void TileGenerator::setDontWriteEmpty(bool f) void TileGenerator::dumpBlock(const std::string &input, BlockPos pos)
{ {
m_dontWriteEmpty = f; std::string input_path = input;
if (input_path.back() != PATH_SEPARATOR)
input_path += PATH_SEPARATOR;
openDb(input_path);
BlockList list;
std::vector<BlockPos> positions;
positions.emplace_back(pos);
m_db->getBlocksByPos(list, positions);
if (!list.empty()) {
const ustring &data = list.begin()->second;
for (u8 c : data)
printf("%02x", static_cast<int>(c));
printf("\n");
}
closeDatabase();
} }
void TileGenerator::generate(const std::string &input, const std::string &output) void TileGenerator::generate(const std::string &input, const std::string &output)
{ {
std::string input_path = input; std::string input_path = input;
if (input_path[input.length() - 1] != PATH_SEPARATOR) { if (input_path.back() != PATH_SEPARATOR)
input_path += PATH_SEPARATOR; input_path += PATH_SEPARATOR;
}
if (m_dontWriteEmpty) // FIXME: possible too, just needs to be done differently if (m_dontWriteEmpty) // FIXME: possible too, just needs to be done differently
setExhaustiveSearch(EXH_NEVER); setExhaustiveSearch(EXH_NEVER);

View File

@ -92,6 +92,8 @@ public:
void generate(const std::string &input, const std::string &output); void generate(const std::string &input, const std::string &output);
void printGeometry(const std::string &input); void printGeometry(const std::string &input);
void dumpBlock(const std::string &input, BlockPos pos);
static std::set<std::string> getSupportedBackends(); static std::set<std::string> getSupportedBackends();
private: private:

View File

@ -13,6 +13,7 @@ struct BlockPos {
int16_t z; int16_t z;
BlockPos() : x(0), y(0), z(0) {} BlockPos() : x(0), y(0), z(0) {}
explicit BlockPos(int16_t v) : x(v), y(v), z(v) {}
BlockPos(int16_t x, int16_t y, int16_t z) : x(x), y(y), z(z) {} BlockPos(int16_t x, int16_t y, int16_t z) : x(x), y(y), z(z) {}
// Implements the inverse ordering so that (2,2,2) < (1,1,1) // Implements the inverse ordering so that (2,2,2) < (1,1,1)

View File

@ -35,6 +35,7 @@ static void usage()
{"--colors", "<colors.txt>"}, {"--colors", "<colors.txt>"},
{"--scales", "[t][b][l][r]"}, {"--scales", "[t][b][l][r]"},
{"--exhaustive", "never|y|full|auto"}, {"--exhaustive", "never|y|full|auto"},
{"--dumpblock", "x,y,z"},
}; };
const char *top_text = const char *top_text =
"minetestmapper -i <world_path> -o <output_image.png> [options]\n" "minetestmapper -i <world_path> -o <output_image.png> [options]\n"
@ -110,15 +111,17 @@ int main(int argc, char *argv[])
{"scales", required_argument, 0, 'f'}, {"scales", required_argument, 0, 'f'},
{"noemptyimage", no_argument, 0, 'n'}, {"noemptyimage", no_argument, 0, 'n'},
{"exhaustive", required_argument, 0, 'j'}, {"exhaustive", required_argument, 0, 'j'},
{"dumpblock", required_argument, 0, 'k'},
{0, 0, 0, 0} {0, 0, 0, 0}
}; };
std::string input; std::string input;
std::string output; std::string output;
std::string colors = ""; std::string colors;
bool onlyPrintExtent = false;
BlockPos dumpblock(INT16_MIN);
TileGenerator generator; TileGenerator generator;
bool onlyPrintExtent = false;
while (1) { while (1) {
int option_index; int option_index;
int c = getopt_long(argc, argv, "hi:o:", long_options, &option_index); int c = getopt_long(argc, argv, "hi:o:", long_options, &option_index);
@ -129,7 +132,6 @@ int main(int argc, char *argv[])
case 'h': case 'h':
usage(); usage();
return 0; return 0;
break;
case 'i': case 'i':
input = optarg; input = optarg;
break; break;
@ -234,12 +236,23 @@ int main(int argc, char *argv[])
generator.setExhaustiveSearch(mode); generator.setExhaustiveSearch(mode);
} }
break; break;
case 'k': {
std::istringstream iss(optarg);
char c, c2;
iss >> dumpblock.x >> c >> dumpblock.y >> c2 >> dumpblock.z;
if (iss.fail() || c != ',' || c2 != ',') {
usage();
exit(1);
}
break;
}
default: default:
exit(1); exit(1);
} }
} }
if (input.empty() || (!onlyPrintExtent && output.empty())) { const bool need_output = !onlyPrintExtent && dumpblock.x == INT16_MIN;
if (input.empty() || (need_output && output.empty())) {
usage(); usage();
return 0; return 0;
} }
@ -249,6 +262,9 @@ int main(int argc, char *argv[])
if (onlyPrintExtent) { if (onlyPrintExtent) {
generator.printGeometry(input); generator.printGeometry(input);
return 0; return 0;
} else if (dumpblock.x != INT16_MIN) {
generator.dumpBlock(input, dumpblock);
return 0;
} }
if(colors == "") if(colors == "")
@ -256,7 +272,7 @@ int main(int argc, char *argv[])
generator.parseColorsFile(colors); generator.parseColorsFile(colors);
generator.generate(input, output); generator.generate(input, output);
} catch (const std::runtime_error &e) { } catch (const std::exception &e) {
std::cerr << "Exception: " << e.what() << std::endl; std::cerr << "Exception: " << e.what() << std::endl;
return 1; return 1;
} }

View File

@ -77,7 +77,7 @@ Use specific map backend; supported: \fIsqlite3\fP, \fIleveldb\fP, \fIredis\fP,
Limit area to specific geometry (\fIx:y+w+h\fP where x and y specify the lower left corner), e.g. "--geometry -800:-800+1600+1600" Limit area to specific geometry (\fIx:y+w+h\fP where x and y specify the lower left corner), e.g. "--geometry -800:-800+1600+1600"
.TP .TP
.BR \-\-extent " " \fIextent\fR .BR \-\-extent
Don't render the image, just print the extent of the map that would be generated, in the same format as the geometry above. Don't render the image, just print the extent of the map that would be generated, in the same format as the geometry above.
.TP .TP
@ -93,7 +93,7 @@ Forcefully set path to colors.txt file (it's autodetected otherwise), e.g. "--co
Draw scales on specified image edges (letters \fIt b l r\fP meaning top, bottom, left and right), e.g. "--scales tbr" Draw scales on specified image edges (letters \fIt b l r\fP meaning top, bottom, left and right), e.g. "--scales tbr"
.TP .TP
.BR \-\-exhaustive " \fImode\fR .BR \-\-exhaustive " " \fImode\fR
Select if database should be traversed exhaustively or using range queries, available: \fInever\fP, \fIy\fP, \fIfull\fP, \fIauto\fP Select if database should be traversed exhaustively or using range queries, available: \fInever\fP, \fIy\fP, \fIfull\fP, \fIauto\fP
Defaults to \fIauto\fP. You shouldn't need to change this, but doing so can improve rendering times on large maps. Defaults to \fIauto\fP. You shouldn't need to change this, but doing so can improve rendering times on large maps.
@ -103,6 +103,10 @@ and
.B max-y .B max-y
when you don't care about the world below e.g. -60 and above 1000 nodes. when you don't care about the world below e.g. -60 and above 1000 nodes.
.TP
.BR \-\-dumpblock " " \fIpos\fR
Instead of rendering anything try to load the block at the given position (\fIx,y,z\fR) and print its raw data as hexadecimal.
.SH MORE INFORMATION .SH MORE INFORMATION
Website: https://github.com/minetest/minetestmapper Website: https://github.com/minetest/minetestmapper