diff --git a/TileGenerator.cpp b/TileGenerator.cpp index 821b3ea..73f653c 100644 --- a/TileGenerator.cpp +++ b/TileGenerator.cpp @@ -254,6 +254,11 @@ void TileGenerator::setExhaustiveSearch(int mode) m_exhaustiveSearch = mode; } +void TileGenerator::setDontWriteEmpty(bool f) +{ + m_dontWriteEmpty = f; +} + void TileGenerator::parseColorsFile(const std::string &fileName) { std::ifstream in(fileName); @@ -265,9 +270,8 @@ void TileGenerator::parseColorsFile(const std::string &fileName) void TileGenerator::printGeometry(const std::string &input) { std::string input_path = input; - if (input_path[input.length() - 1] != PATH_SEPARATOR) { + if (input_path.back() != PATH_SEPARATOR) input_path += PATH_SEPARATOR; - } setExhaustiveSearch(EXH_NEVER); 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 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(c)); + printf("\n"); + } + + closeDatabase(); } void TileGenerator::generate(const std::string &input, const std::string &output) { std::string input_path = input; - if (input_path[input.length() - 1] != PATH_SEPARATOR) { + if (input_path.back() != PATH_SEPARATOR) input_path += PATH_SEPARATOR; - } if (m_dontWriteEmpty) // FIXME: possible too, just needs to be done differently setExhaustiveSearch(EXH_NEVER); diff --git a/include/TileGenerator.h b/include/TileGenerator.h index af4aa26..2648ac7 100644 --- a/include/TileGenerator.h +++ b/include/TileGenerator.h @@ -92,6 +92,8 @@ public: void generate(const std::string &input, const std::string &output); void printGeometry(const std::string &input); + void dumpBlock(const std::string &input, BlockPos pos); + static std::set getSupportedBackends(); private: diff --git a/include/db.h b/include/db.h index 644edc1..836c31b 100644 --- a/include/db.h +++ b/include/db.h @@ -13,6 +13,7 @@ struct BlockPos { int16_t z; 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) {} // Implements the inverse ordering so that (2,2,2) < (1,1,1) diff --git a/mapper.cpp b/mapper.cpp index 13deac1..7ed40f3 100644 --- a/mapper.cpp +++ b/mapper.cpp @@ -35,6 +35,7 @@ static void usage() {"--colors", ""}, {"--scales", "[t][b][l][r]"}, {"--exhaustive", "never|y|full|auto"}, + {"--dumpblock", "x,y,z"}, }; const char *top_text = "minetestmapper -i -o [options]\n" @@ -110,15 +111,17 @@ int main(int argc, char *argv[]) {"scales", required_argument, 0, 'f'}, {"noemptyimage", no_argument, 0, 'n'}, {"exhaustive", required_argument, 0, 'j'}, + {"dumpblock", required_argument, 0, 'k'}, {0, 0, 0, 0} }; std::string input; std::string output; - std::string colors = ""; + std::string colors; + bool onlyPrintExtent = false; + BlockPos dumpblock(INT16_MIN); TileGenerator generator; - bool onlyPrintExtent = false; while (1) { int 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': usage(); return 0; - break; case 'i': input = optarg; break; @@ -234,12 +236,23 @@ int main(int argc, char *argv[]) generator.setExhaustiveSearch(mode); } 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: 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(); return 0; } @@ -249,6 +262,9 @@ int main(int argc, char *argv[]) if (onlyPrintExtent) { generator.printGeometry(input); return 0; + } else if (dumpblock.x != INT16_MIN) { + generator.dumpBlock(input, dumpblock); + return 0; } if(colors == "") @@ -256,7 +272,7 @@ int main(int argc, char *argv[]) generator.parseColorsFile(colors); generator.generate(input, output); - } catch (const std::runtime_error &e) { + } catch (const std::exception &e) { std::cerr << "Exception: " << e.what() << std::endl; return 1; } diff --git a/minetestmapper.6 b/minetestmapper.6 index ceff8f0..c7ced36 100644 --- a/minetestmapper.6 +++ b/minetestmapper.6 @@ -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" .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. .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" .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 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 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 Website: https://github.com/minetest/minetestmapper