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;
}
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<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)
{
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);

View File

@ -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<std::string> getSupportedBackends();
private:

View File

@ -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)

View File

@ -35,6 +35,7 @@ static void usage()
{"--colors", "<colors.txt>"},
{"--scales", "[t][b][l][r]"},
{"--exhaustive", "never|y|full|auto"},
{"--dumpblock", "x,y,z"},
};
const char *top_text =
"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'},
{"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;
}

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"
.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