9 Commits

11 changed files with 434 additions and 57 deletions

View File

@ -21,9 +21,10 @@ if(WIN32)
set(BINDIR ".") set(BINDIR ".")
set(DOCDIR ".") set(DOCDIR ".")
else() else()
set(SHAREDIR "${CMAKE_INSTALL_PREFIX}/share/minetest") # an extra dir. for just one file doesn't seem useful set(SHAREDIR "${CMAKE_INSTALL_PREFIX}/share/minetest") # reuse Minetest share dir
set(BINDIR "${CMAKE_INSTALL_PREFIX}/bin") set(BINDIR "${CMAKE_INSTALL_PREFIX}/bin")
set(DOCDIR "${CMAKE_INSTALL_PREFIX}/share/doc/${PROJECT_NAME}") set(DOCDIR "${CMAKE_INSTALL_PREFIX}/share/doc/${PROJECT_NAME}")
set(MANDIR "${CMAKE_INSTALL_PREFIX}/share/man")
endif() endif()
set(CUSTOM_SHAREDIR "" CACHE STRING "Directory to install data files into") set(CUSTOM_SHAREDIR "" CACHE STRING "Directory to install data files into")
@ -78,6 +79,40 @@ if(NOT SQLITE3_LIBRARY OR NOT SQLITE3_INCLUDE_DIR)
message(FATAL_ERROR "sqlite3 not found!") message(FATAL_ERROR "sqlite3 not found!")
endif(NOT SQLITE3_LIBRARY OR NOT SQLITE3_INCLUDE_DIR) endif(NOT SQLITE3_LIBRARY OR NOT SQLITE3_INCLUDE_DIR)
# Libraries: postgresql
option(ENABLE_POSTGRESQL "Enable PostgreSQL backend" TRUE)
set(USE_POSTGRESQL 0)
if(ENABLE_POSTGRESQL)
find_program(POSTGRESQL_CONFIG_EXECUTABLE pg_config DOC "pg_config")
find_library(POSTGRESQL_LIBRARY pq)
if(POSTGRESQL_CONFIG_EXECUTABLE)
execute_process(COMMAND ${POSTGRESQL_CONFIG_EXECUTABLE} --includedir-server
OUTPUT_VARIABLE POSTGRESQL_SERVER_INCLUDE_DIRS
OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process(COMMAND ${POSTGRESQL_CONFIG_EXECUTABLE}
OUTPUT_VARIABLE POSTGRESQL_CLIENT_INCLUDE_DIRS
OUTPUT_STRIP_TRAILING_WHITESPACE)
# This variable is case sensitive for the cmake PostgreSQL module
set(PostgreSQL_ADDITIONAL_SEARCH_PATHS ${POSTGRESQL_SERVER_INCLUDE_DIRS} ${POSTGRESQL_CLIENT_INCLUDE_DIRS})
endif()
find_package("PostgreSQL")
if(POSTGRESQL_FOUND)
set(USE_POSTGRESQL 1)
message(STATUS "PostgreSQL backend enabled")
# This variable is case sensitive, don't try to change it to POSTGRESQL_INCLUDE_DIR
message(STATUS "PostgreSQL includes: ${PostgreSQL_INCLUDE_DIR}")
include_directories(${PostgreSQL_INCLUDE_DIR})
set(POSTGRESQL_LIBRARY ${PostgreSQL_LIBRARIES})
else()
message(STATUS "PostgreSQL not found.")
set(POSTGRESQL_LIBRARY "")
endif()
endif(ENABLE_POSTGRESQL)
# Libraries: leveldb # Libraries: leveldb
set(USE_LEVELDB 0) set(USE_LEVELDB 0)
@ -148,6 +183,10 @@ set(mapper_SRCS
db-sqlite3.cpp db-sqlite3.cpp
) )
if(USE_POSTGRESQL)
set(mapper_SRCS ${mapper_SRCS} db-postgresql.cpp)
endif(USE_POSTGRESQL)
if(USE_LEVELDB) if(USE_LEVELDB)
set(mapper_SRCS ${mapper_SRCS} db-leveldb.cpp) set(mapper_SRCS ${mapper_SRCS} db-leveldb.cpp)
endif(USE_LEVELDB) endif(USE_LEVELDB)
@ -163,6 +202,7 @@ add_executable(minetestmapper
target_link_libraries( target_link_libraries(
minetestmapper minetestmapper
${SQLITE3_LIBRARY} ${SQLITE3_LIBRARY}
${POSTGRESQL_LIBRARY}
${LEVELDB_LIBRARY} ${LEVELDB_LIBRARY}
${REDIS_LIBRARY} ${REDIS_LIBRARY}
${LIBGD_LIBRARY} ${LIBGD_LIBRARY}
@ -176,6 +216,9 @@ install(FILES "AUTHORS" DESTINATION "${DOCDIR}")
install(FILES "COPYING" DESTINATION "${DOCDIR}") install(FILES "COPYING" DESTINATION "${DOCDIR}")
install(FILES "README.rst" DESTINATION "${DOCDIR}") install(FILES "README.rst" DESTINATION "${DOCDIR}")
install(FILES "colors.txt" DESTINATION "${SHAREDIR}") install(FILES "colors.txt" DESTINATION "${SHAREDIR}")
if(UNIX)
install(FILES "minetestmapper.6" DESTINATION "${MANDIR}/man6")
endif()
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Overview mapper for Minetest") set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Overview mapper for Minetest")
set(CPACK_PACKAGE_VERSION_MAJOR ${VERSION_MAJOR}) set(CPACK_PACKAGE_VERSION_MAJOR ${VERSION_MAJOR})

View File

@ -9,6 +9,8 @@ struct Color {
Color() : r(0), g(0), b(0), a(0) {}; Color() : r(0), g(0), b(0), a(0) {};
Color(u8 r, u8 g, u8 b) : r(r), g(g), b(b), a(255) {}; Color(u8 r, u8 g, u8 b) : r(r), g(g), b(b), a(255) {};
Color(u8 r, u8 g, u8 b, u8 a) : r(r), g(g), b(b), a(a) {}; Color(u8 r, u8 g, u8 b, u8 a) : r(r), g(g), b(b), a(a) {};
inline Color noAlpha() const { return Color(r, g, b); }
u8 r, g, b, a; u8 r, g, b, a;
}; };

View File

@ -12,13 +12,24 @@ Requirements
* libgd * libgd
* sqlite3 * sqlite3
* leveldb (optional, set ENABLE_LEVELDB=1 in CMake to enable leveldb support) * leveldb (optional, set ENABLE_LEVELDB=1 in CMake to enable)
* hiredis (optional, set ENABLE_REDIS=1 in CMake to enable redis support) * hiredis (optional, set ENABLE_REDIS=1 in CMake to enable)
* Postgres libraries (optional, set ENABLE_POSTGRES=1 in CMake to enable)
e.g. on Debian: e.g. on Debian:
^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^
sudo apt-get install libgd-dev libsqlite3-dev libleveldb-dev libhiredis-dev sudo apt-get install libgd-dev libsqlite3-dev libleveldb-dev libhiredis-dev libpq-dev
Windows
^^^^^^^
Minetestmapper for Windows can be downloaded here: https://github.com/minetest/minetestmapper/releases
After extracting the archive somewhere minetestmapper will be available from cmd.exe:
::
cd C:\Users\yourname\Desktop\example\path
minetestmapper.exe --help
Compilation Compilation
----------- -----------
@ -76,7 +87,7 @@ max-y:
Don't draw nodes above this y value, e.g. ``--max-y 75`` Don't draw nodes above this y value, e.g. ``--max-y 75``
backend: backend:
Use specific map backend, supported: *sqlite3*, *leveldb*, *redis*, e.g. ``--backend leveldb`` Use specific map backend; supported: *sqlite3*, *leveldb*, *redis*, *postgresql*, e.g. ``--backend leveldb``
geometry: geometry:
Limit area to specific geometry (*x:y+w+h* where x and y specify the lower left corner), e.g. ``--geometry -800:-800+1600+1600`` Limit area to specific geometry (*x:y+w+h* where x and y specify the lower left corner), e.g. ``--geometry -800:-800+1600+1600``

View File

@ -13,6 +13,9 @@
#include "ZlibDecompressor.h" #include "ZlibDecompressor.h"
#include "util.h" #include "util.h"
#include "db-sqlite3.h" #include "db-sqlite3.h"
#if USE_POSTGRESQL
#include "db-postgresql.h"
#endif
#if USE_LEVELDB #if USE_LEVELDB
#include "db-leveldb.h" #include "db-leveldb.h"
#endif #endif
@ -283,6 +286,10 @@ void TileGenerator::openDb(const std::string &input)
if(backend == "sqlite3") if(backend == "sqlite3")
m_db = new DBSQLite3(input); m_db = new DBSQLite3(input);
#if USE_POSTGRESQL
else if(backend == "postgresql")
m_db = new DBPostgreSQL(input);
#endif
#if USE_LEVELDB #if USE_LEVELDB
else if(backend == "leveldb") else if(backend == "leveldb")
m_db = new DBLevelDB(input); m_db = new DBLevelDB(input);
@ -387,7 +394,9 @@ void TileGenerator::renderMap()
//uint8_t flags = data[1]; //uint8_t flags = data[1];
size_t dataOffset = 0; size_t dataOffset = 0;
if (version >= 22) if (version >= 27)
dataOffset = 6;
else if (version >= 22)
dataOffset = 4; dataOffset = 4;
else else
dataOffset = 2; dataOffset = 2;
@ -526,7 +535,7 @@ void TileGenerator::renderMapBlock(const ustring &mapBlock, const BlockPos &pos,
continue; continue;
} }
} else { } else {
setZoomed(imageX, imageY, c); setZoomed(imageX, imageY, c.noAlpha());
m_readPixels[z] |= (1 << x); m_readPixels[z] |= (1 << x);
} }
if(!(m_readInfo[z] & (1 << x))) { if(!(m_readInfo[z] & (1 << x))) {

View File

@ -1,11 +1,14 @@
==FILE== mods/dumpnodes/init.lua ==FILE== mods/dumpnodes/init.lua
local function nd_get_tiles(nd) local function nd_get_tiles(nd)
if nd.tiles then return nd.tiles or nd.tile_images
return nd.tiles end
elseif nd.tile_images then
return nd.tile_images local function nd_get_tile(nd, n)
local tile = nd_get_tiles(nd)[n]
if type(tile) == 'table' then
tile = tile.name
end end
return nil return tile
end end
local function pairs_s(dict) local function pairs_s(dict)
@ -20,19 +23,19 @@ end
minetest.register_chatcommand("dumpnodes", { minetest.register_chatcommand("dumpnodes", {
params = "", params = "",
description = "", description = "",
func = function(plname, param) func = function(player, param)
local n = 0 local n = 0
local ntbl = {} local ntbl = {}
for _, nn in pairs_s(minetest.registered_nodes) do for _, nn in pairs_s(minetest.registered_nodes) do
local nd = minetest.registered_nodes[nn] local nd = minetest.registered_nodes[nn]
local prefix, name = nn:match('(.*):(.*)') local prefix, name = nn:match('(.*):(.*)')
if prefix == nil or name == nil or prefix == '' or name == '' then if prefix == nil or name == nil then
print("ignored(1): " .. nn) print("ignored(1): " .. nn)
else else
if ntbl[prefix] == nil then if ntbl[prefix] == nil then
ntbl[prefix] = {} ntbl[prefix] = {}
end end
ntbl[prefix][name] = nd ntbl[prefix][name] = true
end end
end end
local out, err = io.open('nodes.txt', 'wb') local out, err = io.open('nodes.txt', 'wb')
@ -40,20 +43,17 @@ minetest.register_chatcommand("dumpnodes", {
return true, "io.open(): " .. err return true, "io.open(): " .. err
end end
for _, prefix in pairs_s(ntbl) do for _, prefix in pairs_s(ntbl) do
local nodes = ntbl[prefix]
out:write('# ' .. prefix .. '\n') out:write('# ' .. prefix .. '\n')
for _, name in pairs_s(nodes) do for _, name in pairs_s(ntbl[prefix]) do
local nd = nodes[name] local nn = prefix .. ":" .. name
if nd.drawtype ~= 'airlike' and nd_get_tiles(nd) ~= nil then local nd = minetest.registered_nodes[nn]
local tl = nd_get_tiles(nd)[1] if nd.drawtype == 'airlike' or nd_get_tiles(nd) == nil then
if type(tl) == 'table' then print("ignored(2): " .. nn)
tl = tl.name
end
tl = (tl .. '^'):match('(.-)^')
out:write(prefix .. ':' .. name .. ' ' .. tl .. '\n')
n = n + 1
else else
print("ignored(2): " .. prefix .. ':' .. name) local tl = nd_get_tile(nd, 1)
tl = (tl .. '^'):match('(.-)^') -- strip modifiers
out:write(nn .. ' ' .. tl .. '\n')
n = n + 1
end end
end end
out:write('\n') out:write('\n')
@ -67,7 +67,7 @@ minetest.register_chatcommand("dumpnodes", {
import sys import sys
from PIL import Image from PIL import Image
def tsum(a, b): def tadd(a, b):
return tuple(sum(e) for e in zip(a, b)) return tuple(sum(e) for e in zip(a, b))
if len(sys.argv) < 2: if len(sys.argv) < 2:
@ -75,8 +75,7 @@ if len(sys.argv) < 2:
print("Usage: %s <input>" % sys.argv[0]) print("Usage: %s <input>" % sys.argv[0])
exit(1) exit(1)
inp = Image.open(sys.argv[1]) inp = Image.open(sys.argv[1]).convert('RGBA')
inp = inp.convert('RGBA')
ind = inp.load() ind = inp.load()
cl = (0, 0, 0) cl = (0, 0, 0)
@ -84,39 +83,36 @@ counted = 0
for x in range(inp.size[0]): for x in range(inp.size[0]):
for y in range(inp.size[1]): for y in range(inp.size[1]):
px = ind[x, y] px = ind[x, y]
if px[3] < 128: if px[3] < 128: continue # alpha
continue cl = tadd(cl, px[:3])
cl = tsum(cl, px[:3]) counted += 1
counted = counted + 1
if counted == 0: if counted == 0:
sys.stderr.write("didn't find avg. color for %s\n" % sys.argv[1]) sys.stderr.write("did not find avg color for %s\n" % sys.argv[1])
print("0 0 0") print("0 0 0")
exit(0) else:
cl = tuple(int(n / counted) for n in cl)
cl = tuple(int(n / counted) for n in cl) print("%d %d %d" % cl)
print("%d %d %d" % cl)
==SCRIPT== ==SCRIPT==
#!/bin/bash -e #!/bin/bash -e
AVGCOLOR_PATH=/path/to/avgcolor.py AVGCOLOR_PATH=/path/to/avgcolor.py
MTGAME_PATH=/path/to/minetest_game GAME_PATH=/path/to/minetest_game
MODS_PATH= # path to "mods" folder, only set if you have loaded mods
NODESTXT_PATH=./nodes.txt NODESTXT_PATH=./nodes.txt
COLORSTXT_PATH=./colors.txt COLORSTXT_PATH=./colors.txt
while read -r line; do while read -r line; do
set -- junk $line set -- junk $line; shift
shift
if [[ -z "$1" || $1 == "#" ]]; then if [[ -z "$1" || $1 == "#" ]]; then
echo $line echo "$line"; continue
continue
fi fi
tex=$(find $MTGAME_PATH -type f -name "$2") tex=$(find $GAME_PATH -type f -name "$2")
[[ -z "$tex" && -n "$MODS_PATH" ]] && tex=$(find $MODS_PATH -type f -name "$2")
if [ -z "$tex" ]; then if [ -z "$tex" ]; then
echo "skip $1: texture not found" >&2 echo "skip $1: texture not found" >&2
continue continue
fi fi
echo $1 $(python $AVGCOLOR_PATH "$tex") echo "$1" $(python $AVGCOLOR_PATH "$tex")
echo "ok $1" >&2 echo "ok $1" >&2
done < $NODESTXT_PATH > $COLORSTXT_PATH done < $NODESTXT_PATH > $COLORSTXT_PATH
# Use nicer colors for water and lava: # Use nicer colors for water and lava:
@ -128,8 +124,8 @@ sed -re 's/^doors:(.*glass[^ ]*) ([0-9 ]+)$/doors:\1 \2 64 16/g' $COLORSTXT_PATH
# Fix xpanes color: # Fix xpanes color:
sed -re 's/^xpanes:((pane|bar)(_flat)?) [0-9 ]+$/xpanes:\1 194 194 227 64 16/g' $COLORSTXT_PATH -i sed -re 's/^xpanes:((pane|bar)(_flat)?) [0-9 ]+$/xpanes:\1 194 194 227 64 16/g' $COLORSTXT_PATH -i
==INSTRUCTIONS== ==INSTRUCTIONS==
1) Make sure avgcolors.py outputs the usage instructions 1) Make sure avgcolors.py works (outputs the usage instructions when run)
2) Add the dumpnodes mod to Minetest 2) Add the dumpnodes mod to Minetest
3) Create a world and load dumpnodes & all mods you want to generate colors for 3) Create a world and load dumpnodes & all mods you want to generate colors for
4) Execute /dumpnodes ingame 4) Execute /dumpnodes ingame
5) Run the script to generate colors.txt (make sure to replace /path/to/... with the actual paths) 5) Run the script to generate colors.txt (make sure to adjust the PATH variables at the top)

View File

@ -3,6 +3,7 @@
#ifndef CMAKE_CONFIG_H #ifndef CMAKE_CONFIG_H
#define CMAKE_CONFIG_H #define CMAKE_CONFIG_H
#define USE_POSTGRESQL @USE_POSTGRESQL@
#define USE_LEVELDB @USE_LEVELDB@ #define USE_LEVELDB @USE_LEVELDB@
#define USE_REDIS @USE_REDIS@ #define USE_REDIS @USE_REDIS@

View File

@ -14,13 +14,14 @@ carts:rail 143 123 90
# default # default
default:acacia_bush_leaves 90 124 55 default:acacia_bush_leaves 90 124 55
default:acacia_bush_sapling 85 118 58
default:acacia_bush_stem 84 76 69 default:acacia_bush_stem 84 76 69
default:acacia_leaves 108 147 67 default:acacia_leaves 108 147 67
default:acacia_sapling 87 116 61 default:acacia_sapling 87 116 61
default:acacia_tree 188 109 90 default:acacia_tree 188 109 90
default:acacia_wood 146 60 37 default:acacia_wood 146 60 37
default:apple 145 20 9 default:apple 145 20 9
default:aspen_leaves 66 89 38 default:aspen_leaves 70 104 27
default:aspen_sapling 82 110 43 default:aspen_sapling 82 110 43
default:aspen_tree 218 197 166 default:aspen_tree 218 197 166
default:aspen_wood 209 198 169 default:aspen_wood 209 198 169
@ -28,10 +29,13 @@ default:bookshelf 128 99 55
default:brick 117 71 69 default:brick 117 71 69
default:bronzeblock 185 110 15 default:bronzeblock 185 110 15
default:bush_leaves 34 52 29 default:bush_leaves 34 52 29
default:bush_sapling 65 60 40
default:bush_stem 45 33 23 default:bush_stem 45 33 23
default:cactus 52 116 15 default:cactus 52 116 15
default:chest 140 108 65 default:chest 140 108 65
default:chest_locked 140 108 65 default:chest_locked 140 108 65
default:chest_locked_open 140 108 65
default:chest_open 140 108 65
default:clay 182 182 182 default:clay 182 182 182
default:cloud 255 255 255 default:cloud 255 255 255
default:coalblock 57 57 57 default:coalblock 57 57 57
@ -42,6 +46,9 @@ default:coral_orange 191 62 12
default:coral_skeleton 235 230 214 default:coral_skeleton 235 230 214
default:desert_cobble 146 95 76 default:desert_cobble 146 95 76
default:desert_sand 206 165 98 default:desert_sand 206 165 98
default:desert_sandstone 195 152 92
default:desert_sandstone_block 192 151 94
default:desert_sandstone_brick 191 151 94
default:desert_stone 129 79 60 default:desert_stone 129 79 60
default:desert_stone_block 130 79 60 default:desert_stone_block 130 79 60
default:desert_stonebrick 129 79 60 default:desert_stonebrick 129 79 60
@ -50,7 +57,8 @@ default:dirt 95 64 39
default:dirt_with_dry_grass 187 148 77 default:dirt_with_dry_grass 187 148 77
default:dirt_with_grass 66 112 31 default:dirt_with_grass 66 112 31
default:dirt_with_grass_footsteps 66 112 31 default:dirt_with_grass_footsteps 66 112 31
default:dirt_with_snow 223 224 236 default:dirt_with_rainforest_litter 74 38 8
default:dirt_with_snow 224 225 238
default:dry_grass_1 208 172 87 default:dry_grass_1 208 172 87
default:dry_grass_2 210 174 87 default:dry_grass_2 210 174 87
default:dry_grass_3 210 174 87 default:dry_grass_3 210 174 87
@ -84,6 +92,7 @@ default:lava_flowing 255 100 0
default:lava_source 255 100 0 default:lava_source 255 100 0
default:leaves 34 52 29 default:leaves 34 52 29
default:mese 220 220 0 default:mese 220 220 0
default:mese_post_light 131 102 57
default:meselamp 211 213 139 default:meselamp 211 213 139
default:mossycobble 86 90 68 default:mossycobble 86 90 68
default:obsidian 19 21 24 default:obsidian 19 21 24
@ -105,8 +114,11 @@ default:sapling 65 59 40
default:sign_wall_steel 144 144 144 default:sign_wall_steel 144 144 144
default:sign_wall_wood 145 101 64 default:sign_wall_wood 145 101 64
default:silver_sand 193 191 179 default:silver_sand 193 191 179
default:snow 223 224 236 default:silver_sandstone 195 192 181
default:snowblock 223 224 236 default:silver_sandstone_block 192 190 179
default:silver_sandstone_brick 190 188 178
default:snow 224 225 238
default:snowblock 224 225 238
default:steelblock 194 194 194 default:steelblock 194 194 194
default:stone 97 94 93 default:stone 97 94 93
default:stone_block 99 96 95 default:stone_block 99 96 95
@ -116,7 +128,9 @@ default:stone_with_diamond 97 94 93
default:stone_with_gold 97 94 93 default:stone_with_gold 97 94 93
default:stone_with_iron 97 94 93 default:stone_with_iron 97 94 93
default:stone_with_mese 97 94 93 default:stone_with_mese 97 94 93
default:stone_with_tin 97 94 93
default:stonebrick 99 96 95 default:stonebrick 99 96 95
default:tinblock 149 149 149
default:torch 120 98 67 default:torch 120 98 67
default:torch_ceiling 120 98 67 default:torch_ceiling 120 98 67
default:torch_wall 120 98 67 default:torch_wall 120 98 67
@ -190,10 +204,6 @@ flowers:tulip 130 99 36
flowers:viola 106 60 159 flowers:viola 106 60 159
flowers:waterlily 102 158 61 flowers:waterlily 102 158 61
# nyancat
nyancat:nyancat 198 111 167
nyancat:nyancat_rainbow 123 100 94
# stairs # stairs
stairs:slab_acacia_wood 146 60 37 stairs:slab_acacia_wood 146 60 37
stairs:slab_aspen_wood 209 198 169 stairs:slab_aspen_wood 209 198 169
@ -202,10 +212,14 @@ stairs:slab_bronzeblock 185 110 15
stairs:slab_cobble 88 84 82 stairs:slab_cobble 88 84 82
stairs:slab_copperblock 192 126 63 stairs:slab_copperblock 192 126 63
stairs:slab_desert_cobble 146 95 76 stairs:slab_desert_cobble 146 95 76
stairs:slab_desert_sandstone 195 152 92
stairs:slab_desert_sandstone_block 192 151 94
stairs:slab_desert_sandstone_brick 191 151 94
stairs:slab_desert_stone 129 79 60 stairs:slab_desert_stone 129 79 60
stairs:slab_desert_stone_block 130 79 60 stairs:slab_desert_stone_block 130 79 60
stairs:slab_desert_stonebrick 129 79 60 stairs:slab_desert_stonebrick 129 79 60
stairs:slab_goldblock 230 201 29 stairs:slab_goldblock 230 201 29
stairs:slab_ice 167 206 247
stairs:slab_junglewood 54 37 11 stairs:slab_junglewood 54 37 11
stairs:slab_mossycobble 86 90 68 stairs:slab_mossycobble 86 90 68
stairs:slab_obsidian 19 21 24 stairs:slab_obsidian 19 21 24
@ -215,6 +229,10 @@ stairs:slab_pine_wood 221 184 128
stairs:slab_sandstone 197 193 143 stairs:slab_sandstone 197 193 143
stairs:slab_sandstone_block 195 190 141 stairs:slab_sandstone_block 195 190 141
stairs:slab_sandstonebrick 193 189 140 stairs:slab_sandstonebrick 193 189 140
stairs:slab_silver_sandstone 195 192 181
stairs:slab_silver_sandstone_block 192 190 179
stairs:slab_silver_sandstone_brick 190 188 178
stairs:slab_snowblock 224 225 238
stairs:slab_steelblock 194 194 194 stairs:slab_steelblock 194 194 194
stairs:slab_stone 97 94 93 stairs:slab_stone 97 94 93
stairs:slab_stone_block 99 96 95 stairs:slab_stone_block 99 96 95
@ -228,10 +246,14 @@ stairs:stair_bronzeblock 185 110 15
stairs:stair_cobble 88 84 82 stairs:stair_cobble 88 84 82
stairs:stair_copperblock 192 126 63 stairs:stair_copperblock 192 126 63
stairs:stair_desert_cobble 146 95 76 stairs:stair_desert_cobble 146 95 76
stairs:stair_desert_sandstone 195 152 92
stairs:stair_desert_sandstone_block 192 151 94
stairs:stair_desert_sandstone_brick 191 151 94
stairs:stair_desert_stone 129 79 60 stairs:stair_desert_stone 129 79 60
stairs:stair_desert_stone_block 130 79 60 stairs:stair_desert_stone_block 130 79 60
stairs:stair_desert_stonebrick 129 79 60 stairs:stair_desert_stonebrick 129 79 60
stairs:stair_goldblock 230 201 29 stairs:stair_goldblock 230 201 29
stairs:stair_ice 167 206 247
stairs:stair_junglewood 54 37 11 stairs:stair_junglewood 54 37 11
stairs:stair_mossycobble 86 90 68 stairs:stair_mossycobble 86 90 68
stairs:stair_obsidian 19 21 24 stairs:stair_obsidian 19 21 24
@ -241,6 +263,10 @@ stairs:stair_pine_wood 221 184 128
stairs:stair_sandstone 197 193 143 stairs:stair_sandstone 197 193 143
stairs:stair_sandstone_block 195 190 141 stairs:stair_sandstone_block 195 190 141
stairs:stair_sandstonebrick 193 189 140 stairs:stair_sandstonebrick 193 189 140
stairs:stair_silver_sandstone 195 192 181
stairs:stair_silver_sandstone_block 192 190 179
stairs:stair_silver_sandstone_brick 190 188 178
stairs:stair_snowblock 224 225 238
stairs:stair_steelblock 194 194 194 stairs:stair_steelblock 194 194 194
stairs:stair_stone 97 94 93 stairs:stair_stone 97 94 93
stairs:stair_stone_block 99 96 95 stairs:stair_stone_block 99 96 95

View File

@ -9,6 +9,7 @@
#ifdef USE_CMAKE_CONFIG_H #ifdef USE_CMAKE_CONFIG_H
#include "cmake_config.h" #include "cmake_config.h"
#else #else
#define USE_POSTGRESQL 0
#define USE_LEVELDB 0 #define USE_LEVELDB 0
#define USE_REDIS 0 #define USE_REDIS 0

168
db-postgresql.cpp Normal file
View File

@ -0,0 +1,168 @@
#include <stdexcept>
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <arpa/inet.h>
#include "db-postgresql.h"
#include "util.h"
#include "types.h"
#define ARRLEN(x) (sizeof(x) / sizeof((x)[0]))
DBPostgreSQL::DBPostgreSQL(const std::string &mapdir)
{
std::ifstream ifs((mapdir + "/world.mt").c_str());
if(!ifs.good())
throw std::runtime_error("Failed to read world.mt");
std::string const connect_string = get_setting("pgsql_connection", ifs);
ifs.close();
db = PQconnectdb(connect_string.c_str());
if (PQstatus(db) != CONNECTION_OK) {
throw std::runtime_error(std::string(
"PostgreSQL database error: ") +
PQerrorMessage(db)
);
}
prepareStatement(
"get_block_pos",
"SELECT posX, posY, posZ FROM blocks"
);
prepareStatement(
"get_blocks_z",
"SELECT posX, posY, data FROM blocks WHERE posZ = $1::int4"
);
checkResults(PQexec(db, "START TRANSACTION;"));
checkResults(PQexec(db, "SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;"));
}
DBPostgreSQL::~DBPostgreSQL()
{
try {
checkResults(PQexec(db, "COMMIT;"));
} catch (std::exception& caught) {
std::cerr << "could not finalize: " << caught.what() << std::endl;
}
PQfinish(db);
}
std::vector<BlockPos> DBPostgreSQL::getBlockPos()
{
std::vector<BlockPos> positions;
PGresult *results = execPrepared(
"get_block_pos", 0,
NULL, NULL, NULL, false, false
);
int numrows = PQntuples(results);
for (int row = 0; row < numrows; ++row)
positions.push_back(pg_to_blockpos(results, row, 0));
PQclear(results);
return positions;
}
void DBPostgreSQL::getBlocksOnZ(std::map<int16_t, BlockList> &blocks, int16_t zPos)
{
int32_t const z = htonl(zPos);
const void *args[] = { &z };
const int argLen[] = { sizeof(z) };
const int argFmt[] = { 1 };
PGresult *results = execPrepared(
"get_blocks_z", ARRLEN(args), args,
argLen, argFmt, false
);
int numrows = PQntuples(results);
for (int row = 0; row < numrows; ++row) {
BlockPos position;
position.x = pg_binary_to_int(results, row, 0);
position.y = pg_binary_to_int(results, row, 1);
position.z = zPos;
Block const b(
position,
ustring(
reinterpret_cast<unsigned char*>(
PQgetvalue(results, row, 2)
),
PQgetlength(results, row, 2)
)
);
blocks[position.x].push_back(b);
}
PQclear(results);
}
PGresult *DBPostgreSQL::checkResults(PGresult *res, bool clear)
{
ExecStatusType statusType = PQresultStatus(res);
switch (statusType) {
case PGRES_COMMAND_OK:
case PGRES_TUPLES_OK:
break;
case PGRES_FATAL_ERROR:
throw std::runtime_error(
std::string("PostgreSQL database error: ") +
PQresultErrorMessage(res)
);
default:
throw std::runtime_error(
"Unhandled PostgreSQL result code"
);
}
if (clear)
PQclear(res);
return res;
}
void DBPostgreSQL::prepareStatement(const std::string &name, const std::string &sql)
{
checkResults(PQprepare(db, name.c_str(), sql.c_str(), 0, NULL));
}
PGresult *DBPostgreSQL::execPrepared(
const char *stmtName, const int paramsNumber,
const void **params,
const int *paramsLengths, const int *paramsFormats,
bool clear, bool nobinary
)
{
return checkResults(PQexecPrepared(db, stmtName, paramsNumber,
(const char* const*) params, paramsLengths, paramsFormats,
nobinary ? 1 : 0), clear
);
}
int DBPostgreSQL::pg_to_int(PGresult *res, int row, int col)
{
return atoi(PQgetvalue(res, row, col));
}
int DBPostgreSQL::pg_binary_to_int(PGresult *res, int row, int col)
{
int32_t* raw = reinterpret_cast<int32_t*>(PQgetvalue(res, row, col));
return ntohl(*raw);
}
BlockPos DBPostgreSQL::pg_to_blockpos(PGresult *res, int row, int col)
{
BlockPos result;
result.x = pg_to_int(res, row, col);
result.y = pg_to_int(res, row, col + 1);
result.z = pg_to_int(res, row, col + 2);
return result;
}

29
db-postgresql.h Normal file
View File

@ -0,0 +1,29 @@
#ifndef _DB_POSTGRESQL_H
#define _DB_POSTGRESQL_H
#include "db.h"
#include <libpq-fe.h>
class DBPostgreSQL : public DB {
public:
DBPostgreSQL(const std::string &mapdir);
virtual std::vector<BlockPos> getBlockPos();
virtual void getBlocksOnZ(std::map<int16_t, BlockList> &blocks, int16_t zPos);
virtual ~DBPostgreSQL();
protected:
PGresult *checkResults(PGresult *res, bool clear = true);
void prepareStatement(const std::string &name, const std::string &sql);
PGresult *execPrepared(
const char *stmtName, const int paramsNumber,
const void **params,
const int *paramsLengths = NULL, const int *paramsFormats = NULL,
bool clear = true, bool nobinary = true
);
int pg_to_int(PGresult *res, int row, int col);
int pg_binary_to_int(PGresult *res, int row, int col);
BlockPos pg_to_blockpos(PGresult *res, int row, int col);
private:
PGconn *db;
};
#endif // _DB_POSTGRESQL_H

91
minetestmapper.6 Normal file
View File

@ -0,0 +1,91 @@
.TH MINETESTMAPPER 6
.SH NAME
minetestmapper \- generate an overview image of a Minetest map
.SH SYNOPSIS
.B minetestmapper
\fB\-i\fR \fIworld_path\fR
\fB\-o\fR \fIoutput_image\fR
.PP
See additional optional parameters below.
.SH DESCRIPTION
.B minetestmapper
generates an overview image of a minetest map. This is a port of
the original minetestmapper.py to C++, that is both faster and
provides more funtionality than the deprecated Python script.
.SH MANDATORY PARAMETERS
.TP
.BR \-i " " \fIworld_path\fR
Input world path.
.TP
.BR \-o " " \fIoutput_image\fR
Path to output image. (only PNG supported currently)
.SH OPTIONAL PARAMETERS
.TP
.BR \-\-bgcolor " " \fIcolor\fR
Background color of image, e.g. "--bgcolor #ffffff"
.TP
.BR \-\-scalecolor " " \fIcolor\fR
Color of scale, e.g. "--scalecolor #000000"
.TP
.BR \-\-playercolor " " \fIcolor\fR
Color of player indicators, e.g. "--playercolor #ff0000"
.TP
.BR \-\-origincolor " " \fIcolor\fR
Color of origin indicator, e.g. "--origincolor #ff0000"
.TP
.BR \-\-drawscale
Draw tick marks
.TP
.BR \-\-drawplayers
Draw player indicators
.TP
.BR \-\-draworigin
Draw origin indicator
.TP
.BR \-\-drawalpha
Allow nodes to be drawn with transparency
.TP
.BR \-\-noshading
Don't draw shading on nodes
.TP
.BR \-\-min-y " " \fInumber\fR
Don't draw nodes below this y value, e.g. "--min-y -25"
.TP
.BR \-\-max-y " " \fInumber\fR
Don't draw nodes above this y value, e.g. "--max-y 75"
.TP
.BR \-\-backend " " \fIbackend\fR
Use specific map backend; supported: *sqlite3*, *leveldb*, *redis*, *postgresql*, e.g. "--backend leveldb"
.TP
.BR \-\-geometry " " \fIgeometry\fR
Limit area to specific geometry (*x:y+w+h* where x and y specify the lower left corner), e.g. "--geometry -800:-800+1600+1600"
.TP
.BR \-\-zoom " " \fIfactor\fR
Zoom the image by using more than one pixel per node, e.g. "--zoom 4"
.TP
.BR \-\-colors " " \fIpath\fR
Forcefully set path to colors.txt file (it's autodetected otherwise), e.g. "--colors ../minetest/mycolors.txt"
.TP
.BR \-\-scales " " \fIedges\fR
Draw scales on specified image edges (letters *t b l r* meaning top, bottom, left and right), e.g. "--scales tbr"
.SH MORE INFORMATION
Website: https://github.com/minetest/minetestmapper
.SH MAN PAGE AUTHOR
Daniel Moerner