Codebase list minetestmapper / fresh-snapshots/main
New upstream snapshot. Debian Janitor 2 years ago
38 changed file(s) with 850 addition(s) and 556 deletion(s). Raw diff Collapse all Expand all
0 name: build
1
2 # build on c/cpp changes or workflow changes
3 on:
4 push:
5 paths:
6 - '**.[ch]'
7 - '**.cpp'
8 - '**/CMakeLists.txt'
9 - '.github/workflows/**.yml'
10 pull_request:
11 paths:
12 - '**.[ch]'
13 - '**.cpp'
14 - '**/CMakeLists.txt'
15 - '.github/workflows/**.yml'
16
17 jobs:
18 gcc:
19 runs-on: ubuntu-20.04
20 steps:
21 - uses: actions/checkout@v2
22 - name: Install deps
23 run: |
24 source util/ci/script.sh
25 install_linux_deps
26
27 - name: Build
28 run: |
29 source util/ci/script.sh
30 run_build
31 env:
32 CC: gcc
33 CXX: g++
34
35 - name: Test
36 run: |
37 source util/ci/script.sh
38 do_functional_test
39
40 clang:
41 runs-on: ubuntu-20.04
42 steps:
43 - uses: actions/checkout@v2
44 - name: Install deps
45 run: |
46 source util/ci/script.sh
47 install_linux_deps
48
49 - name: Build
50 run: |
51 source util/ci/script.sh
52 run_build
53 env:
54 CC: clang
55 CXX: clang++
56
57 - name: Test
58 run: |
59 source util/ci/script.sh
60 do_functional_test
0 colors.txt
0 *~
1
12 minetestmapper
23 minetestmapper.exe
4 colors.txt
5
36 CMakeCache.txt
47 CMakeFiles/
5 CPack*
8 CPack*.cmake
9 _CPack_Packages/
10 install_manifest.txt
611 Makefile
712 cmake_install.cmake
813 cmake_config.h
9 *~
+0
-19
.travis.yml less more
0 language: cpp
1 compiler:
2 - gcc
3 - clang
4 dist: bionic
5 addons:
6 apt:
7 packages:
8 - cmake
9 - libgd-dev
10 - libsqlite3-dev
11 - libleveldb-dev
12 - libpq-dev
13 - postgresql-server-dev-all
14 script: ./util/travis/script.sh
15 notifications:
16 email: false
17 matrix:
18 fast_finish: true
0 #include <stdint.h>
10 #include <string>
21 #include <iostream>
32 #include <sstream>
109 return data[0] << 8 | data[1];
1110 }
1211
13 static int readBlockContent(const unsigned char *mapData, u8 version, unsigned int datapos)
12 static inline uint16_t readBlockContent(const unsigned char *mapData,
13 u8 contentWidth, unsigned int datapos)
1414 {
15 if (version >= 24) {
15 if (contentWidth == 2) {
1616 size_t index = datapos << 1;
1717 return (mapData[index] << 8) | mapData[index + 1];
18 } else if (version >= 20) {
19 if (mapData[datapos] <= 0x80)
20 return mapData[datapos];
18 } else {
19 u8 param = mapData[datapos];
20 if (param <= 0x7f)
21 return param;
2122 else
22 return (int(mapData[datapos]) << 4) | (int(mapData[datapos + 0x2000]) >> 4);
23 return (param << 4) | (mapData[datapos + 0x2000] >> 4);
2324 }
24 std::ostringstream oss;
25 oss << "Unsupported map version " << version;
26 throw std::runtime_error(oss.str());
2725 }
2826
2927 BlockDecoder::BlockDecoder()
3836 m_nameMap.clear();
3937
4038 m_version = 0;
41 m_mapData = ustring();
39 m_contentWidth = 0;
40 m_mapData.clear();
4241 }
4342
4443 void BlockDecoder::decode(const ustring &datastr)
4847 // TODO: bounds checks
4948
5049 uint8_t version = data[0];
51 //uint8_t flags = data[1];
50 if (version < 22) {
51 std::ostringstream oss;
52 oss << "Unsupported map version " << (int)version;
53 throw std::runtime_error(oss.str());
54 }
5255 m_version = version;
5356
57 ustring datastr2;
58 if (version >= 29) {
59 // decompress whole block at once
60 m_zstd_decompressor.setData(data, length, 1);
61 datastr2 = m_zstd_decompressor.decompress();
62 data = datastr2.c_str();
63 length = datastr2.size();
64 }
65
5466 size_t dataOffset = 0;
55 if (version >= 27)
56 dataOffset = 6;
57 else if (version >= 22)
67 if (version >= 29)
68 dataOffset = 7;
69 else if (version >= 27)
5870 dataOffset = 4;
5971 else
6072 dataOffset = 2;
6173
74 auto decode_mapping = [&] () {
75 dataOffset++; // mapping version
76 uint16_t numMappings = readU16(data + dataOffset);
77 dataOffset += 2;
78 for (int i = 0; i < numMappings; ++i) {
79 uint16_t nodeId = readU16(data + dataOffset);
80 dataOffset += 2;
81 uint16_t nameLen = readU16(data + dataOffset);
82 dataOffset += 2;
83 std::string name(reinterpret_cast<const char *>(data) + dataOffset, nameLen);
84 if (name == "air")
85 m_blockAirId = nodeId;
86 else if (name == "ignore")
87 m_blockIgnoreId = nodeId;
88 else
89 m_nameMap[nodeId] = name;
90 dataOffset += nameLen;
91 }
92 };
93
94 if (version >= 29)
95 decode_mapping();
96
97 uint8_t contentWidth = data[dataOffset];
98 dataOffset++;
99 uint8_t paramsWidth = data[dataOffset];
100 dataOffset++;
101 if (contentWidth != 1 && contentWidth != 2)
102 throw std::runtime_error("unsupported map version (contentWidth)");
103 if (paramsWidth != 2)
104 throw std::runtime_error("unsupported map version (paramsWidth)");
105 m_contentWidth = contentWidth;
106
107 if (version >= 29) {
108 m_mapData.resize((contentWidth + paramsWidth) * 4096);
109 m_mapData.assign(data + dataOffset, m_mapData.size());
110 return; // we have read everything we need and can return early
111 }
112
113 // version < 29
62114 ZlibDecompressor decompressor(data, length);
63115 decompressor.setSeekPos(dataOffset);
64116 m_mapData = decompressor.decompress();
65117 decompressor.decompress(); // unused metadata
66118 dataOffset = decompressor.seekPos();
67119
68 // Skip unused data
69 if (version <= 21)
70 dataOffset += 2;
120 // Skip unused node timers
71121 if (version == 23)
72122 dataOffset += 1;
73123 if (version == 24) {
91141 dataOffset += 4; // Skip timestamp
92142
93143 // Read mapping
94 if (version >= 22) {
95 dataOffset++; // mapping version
96 uint16_t numMappings = readU16(data + dataOffset);
97 dataOffset += 2;
98 for (int i = 0; i < numMappings; ++i) {
99 uint16_t nodeId = readU16(data + dataOffset);
100 dataOffset += 2;
101 uint16_t nameLen = readU16(data + dataOffset);
102 dataOffset += 2;
103 std::string name(reinterpret_cast<const char *>(data) + dataOffset, nameLen);
104 if (name == "air")
105 m_blockAirId = nodeId;
106 else if (name == "ignore")
107 m_blockIgnoreId = nodeId;
108 else
109 m_nameMap[nodeId] = name;
110 dataOffset += nameLen;
111 }
112 }
113
114 // Node timers
115 if (version >= 25) {
116 dataOffset++;
117 uint16_t numTimers = readU16(data + dataOffset);
118 dataOffset += 2;
119 dataOffset += numTimers * 10;
120 }
144 decode_mapping();
121145 }
122146
123147 bool BlockDecoder::isEmpty() const
126150 return m_nameMap.empty();
127151 }
128152
129 std::string BlockDecoder::getNode(u8 x, u8 y, u8 z) const
153 const static std::string empty;
154
155 const std::string &BlockDecoder::getNode(u8 x, u8 y, u8 z) const
130156 {
131157 unsigned int position = x + (y << 4) + (z << 8);
132 int content = readBlockContent(m_mapData.c_str(), m_version, position);
158 uint16_t content = readBlockContent(m_mapData.c_str(), m_contentWidth, position);
133159 if (content == m_blockAirId || content == m_blockIgnoreId)
134 return "";
160 return empty;
135161 NameMap::const_iterator it = m_nameMap.find(content);
136162 if (it == m_nameMap.end()) {
137163 std::cerr << "Skipping node with invalid ID." << std::endl;
138 return "";
164 return empty;
139165 }
140166 return it->second;
141167 }
0 project(minetestmapper CXX)
1 cmake_minimum_required(VERSION 2.6)
2 cmake_policy(SET CMP0003 NEW)
3
4 set(VERSION_MAJOR 1)
5 set(VERSION_MINOR 0)
6 set(VERSION_STRING "${VERSION_MAJOR}.${VERSION_MINOR}")
0 cmake_minimum_required(VERSION 3.5)
1
2 project(minetestmapper
3 VERSION 1.0
4 LANGUAGES CXX
5 )
76
87 # Stuff & Paths
98
1211 endif()
1312
1413 set(CMAKE_CXX_STANDARD 11)
15 set(CMAKE_CXX_FLAGS_RELEASE "-O3 -Wall -DNDEBUG")
16 set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g2 -Wall")
14 set(CMAKE_CXX_STANDARD_REQUIRED ON)
1715
1816 if(WIN32)
1917 set(SHAREDIR ".")
2018 set(BINDIR ".")
2119 set(DOCDIR ".")
2220 else()
23 set(SHAREDIR "${CMAKE_INSTALL_PREFIX}/share/minetest") # reuse Minetest share dir
24 set(BINDIR "${CMAKE_INSTALL_PREFIX}/bin")
25 set(DOCDIR "${CMAKE_INSTALL_PREFIX}/share/doc/${PROJECT_NAME}")
26 set(MANDIR "${CMAKE_INSTALL_PREFIX}/share/man")
21 set(SHAREDIR "share/minetest") # reuse Minetest share dir
22 set(BINDIR "bin")
23 set(DOCDIR "share/doc/${PROJECT_NAME}")
24 set(MANDIR "share/man")
2725 endif()
2826
2927 set(CUSTOM_SHAREDIR "" CACHE STRING "Directory to install data files into")
4442 message(STATUS "Using DOCDIR=${DOCDIR}")
4543 endif()
4644
47 #set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
48 find_package(PkgConfig)
49 include(FindPackageHandleStandardArgs)
45 set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
5046
5147 # Libraries: gd
5248
6056
6157 # Libraries: zlib
6258
63 find_library(ZLIB_LIBRARY z)
64 find_path(ZLIB_INCLUDE_DIR zlib.h)
65 message (STATUS "zlib library: ${ZLIB_LIBRARY}")
66 message (STATUS "zlib headers: ${ZLIB_INCLUDE_DIR}")
67 if(NOT ZLIB_LIBRARY OR NOT ZLIB_INCLUDE_DIR)
68 message(FATAL_ERROR "zlib not found!")
69 endif(NOT ZLIB_LIBRARY OR NOT ZLIB_INCLUDE_DIR)
59 find_package(ZLIB REQUIRED)
60
61 # Libraries: zstd
62
63 find_package(Zstd REQUIRED)
7064
7165 # Libraries: sqlite3
7266
7367 find_library(SQLITE3_LIBRARY sqlite3)
74 find_path(SQLITE3_INCLUDE_DIR zlib.h)
68 find_path(SQLITE3_INCLUDE_DIR sqlite3.h)
7569 message (STATUS "sqlite3 library: ${SQLITE3_LIBRARY}")
7670 message (STATUS "sqlite3 headers: ${SQLITE3_INCLUDE_DIR}")
7771 if(NOT SQLITE3_LIBRARY OR NOT SQLITE3_INCLUDE_DIR)
8478 set(USE_POSTGRESQL FALSE)
8579
8680 if(ENABLE_POSTGRESQL)
87 find_package("PostgreSQL")
81 if(CMAKE_VERSION VERSION_LESS "3.20")
82 find_package(PostgreSQL QUIET)
83 # Before CMake 3.20 FindPostgreSQL.cmake always looked for server includes
84 # but we don't need them, so continue anyway if only those are missing.
85 if(PostgreSQL_INCLUDE_DIR AND PostgreSQL_LIBRARY)
86 set(PostgreSQL_FOUND TRUE)
87 set(PostgreSQL_INCLUDE_DIRS ${PostgreSQL_INCLUDE_DIR})
88 endif()
89 else()
90 find_package(PostgreSQL)
91 endif()
8892
8993 if(PostgreSQL_FOUND)
9094 set(USE_POSTGRESQL TRUE)
147151 ${SQLITE3_INCLUDE_DIR}
148152 ${LIBGD_INCLUDE_DIR}
149153 ${ZLIB_INCLUDE_DIR}
154 ${ZSTD_INCLUDE_DIR}
150155 )
151156
152157 configure_file(
153158 "${PROJECT_SOURCE_DIR}/include/cmake_config.h.in"
154159 "${PROJECT_BINARY_DIR}/cmake_config.h"
155160 )
156 add_definitions ( -DUSE_CMAKE_CONFIG_H )
157
158 set(mapper_SRCS
161 add_definitions(-DUSE_CMAKE_CONFIG_H)
162
163 if(CMAKE_CXX_COMPILER_ID MATCHES "^(GNU|Clang|AppleClang)$")
164 set(CMAKE_CXX_FLAGS_RELEASE "-O2")
165 set(CMAKE_CXX_FLAGS_DEBUG "-Og -g2")
166 add_compile_options(-Wall -pipe)
167 endif()
168 if(CMAKE_BUILD_TYPE STREQUAL "Release")
169 add_definitions(-DNDEBUG)
170 endif()
171
172 add_executable(minetestmapper
159173 BlockDecoder.cpp
160174 PixelAttributes.cpp
161175 PlayerAttributes.cpp
162176 TileGenerator.cpp
163177 ZlibDecompressor.cpp
178 ZstdDecompressor.cpp
164179 Image.cpp
165180 mapper.cpp
166181 util.cpp
167182 db-sqlite3.cpp
168 )
169
170 if(USE_POSTGRESQL)
171 set(mapper_SRCS ${mapper_SRCS} db-postgresql.cpp)
172 endif(USE_POSTGRESQL)
173
174 if(USE_LEVELDB)
175 set(mapper_SRCS ${mapper_SRCS} db-leveldb.cpp)
176 endif(USE_LEVELDB)
177
178 if(USE_REDIS)
179 set(mapper_SRCS ${mapper_SRCS} db-redis.cpp)
180 endif(USE_REDIS)
181
182 add_executable(minetestmapper
183 ${mapper_SRCS}
183 $<$<BOOL:${USE_POSTGRESQL}>:db-postgresql.cpp>
184 $<$<BOOL:${USE_LEVELDB}>:db-leveldb.cpp>
185 $<$<BOOL:${USE_REDIS}>:db-redis.cpp>
184186 )
185187
186188 target_link_libraries(
191193 ${REDIS_LIBRARY}
192194 ${LIBGD_LIBRARY}
193195 ${ZLIB_LIBRARY}
196 ${ZSTD_LIBRARY}
194197 )
195198
196199 # Installing & Packaging
205208 endif()
206209
207210 set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Overview mapper for Minetest")
208 set(CPACK_PACKAGE_VERSION_MAJOR ${VERSION_MAJOR})
209 set(CPACK_PACKAGE_VERSION_MINOR ${VERSION_MINOR})
210211 set(CPACK_PACKAGE_VENDOR "celeron55")
211212 set(CPACK_PACKAGE_CONTACT "Perttu Ahola <celeron55@gmail.com>")
212213
213214 if(WIN32)
214 set(CPACK_PACKAGE_FILE_NAME "${PROJECT_NAME}-${VERSION_STRING}-win32")
215 set(CPACK_PACKAGE_FILE_NAME "${PROJECT_NAME}-${PROJECT_VERSION}-win32")
215216 set(CPACK_GENERATOR ZIP)
216217 else()
217 set(CPACK_PACKAGE_FILE_NAME "${PROJECT_NAME}-${VERSION_STRING}-linux")
218 set(CPACK_PACKAGE_FILE_NAME "${PROJECT_NAME}-${PROJECT_VERSION}-linux")
218219 set(CPACK_GENERATOR TGZ)
219220 set(CPACK_SOURCE_GENERATOR TGZ)
220221 endif()
1616
1717 // ARGB but with inverted alpha
1818
19 static inline int color2int(Color c)
19 static inline int color2int(const Color &c)
2020 {
2121 u8 a = (255 - c.a) * gdAlphaMax / 255;
2222 return (a << 24) | (c.r << 16) | (c.g << 8) | c.b;
3434 return c2;
3535 }
3636
37 #ifndef NDEBUG
3738 static inline void check_bounds(int x, int y, int width, int height)
3839 {
3940 if(x < 0 || x >= width) {
4950 throw std::out_of_range(oss.str());
5051 }
5152 }
53 #endif
5254
5355
5456 Image::Image(int width, int height) :
5557 m_width(width), m_height(height), m_image(NULL)
5658 {
59 SIZECHECK(0, 0);
5760 m_image = gdImageCreateTrueColor(m_width, m_height);
5861 }
5962
0 /*
1 * =====================================================================
2 * Version: 1.0
3 * Created: 25.08.2012 10:55:27
4 * Author: Miroslav Bendík
5 * Company: LinuxOS.sk
6 * =====================================================================
7 */
0 #include <cstring>
81
92 #include "PixelAttributes.h"
10 #include <cstring>
113
124 PixelAttributes::PixelAttributes():
135 m_width(0)
88 #include "PlayerAttributes.h"
99 #include "util.h"
1010
11 using namespace std;
12
1311 PlayerAttributes::PlayerAttributes(const std::string &worldDir)
1412 {
15 std::ifstream ifs((worldDir + "world.mt").c_str());
13 std::ifstream ifs(worldDir + "world.mt");
1614 if (!ifs.good())
1715 throw std::runtime_error("Failed to read world.mt");
1816 std::string backend = read_setting_default("player_backend", ifs, "files");
3836 if (ent->d_name[0] == '.')
3937 continue;
4038
41 string path = playersPath + PATH_SEPARATOR + ent->d_name;
42 ifstream in(path.c_str());
39 std::string path = playersPath + PATH_SEPARATOR + ent->d_name;
40 std::ifstream in(path);
4341 if(!in.good())
4442 continue;
4543
46 string name, position;
44 std::string name, position;
4745 name = read_setting("name", in);
4846 in.seekg(0);
4947 position = read_setting("position", in);
5048
5149 Player player;
52 istringstream iss(position);
50 std::istringstream iss(position);
5351 char tmp;
5452 iss >> tmp; // '('
5553 iss >> player.x;
120118
121119 /**********/
122120
123 PlayerAttributes::Players::iterator PlayerAttributes::begin()
121 PlayerAttributes::Players::const_iterator PlayerAttributes::begin() const
124122 {
125 return m_players.begin();
123 return m_players.cbegin();
126124 }
127125
128 PlayerAttributes::Players::iterator PlayerAttributes::end()
126 PlayerAttributes::Players::const_iterator PlayerAttributes::end() const
129127 {
130 return m_players.end();
128 return m_players.cend();
131129 }
132130
00 Minetest Mapper C++
11 ===================
22
3 .. image:: https://travis-ci.org/minetest/minetestmapper.svg?branch=master
4 :target: https://travis-ci.org/minetest/minetestmapper
3 .. image:: https://github.com/minetest/minetestmapper/workflows/build/badge.svg
4 :target: https://github.com/minetest/minetestmapper/actions/workflows/build.yml
55
6 A port of minetestmapper.py to C++ from https://github.com/minetest/minetest/tree/master/util.
7 This version is both faster and provides more features than the now deprecated Python script.
6 Minetestmapper generates an overview image from a Minetest map.
7
8 A port of minetestmapper.py to C++ from https://github.com/minetest/minetest/tree/0.4.17/util.
9 This version is both faster and provides more features than the now obsolete Python script.
10
11 Minetestmapper ships with a colors.txt file for Minetest Game, if you use a different game or have
12 many mods installed you should generate a matching colors.txt for better results.
13 The `generate_colorstxt.py script
14 <./util/generate_colorstxt.py>`_ in the util folder exists for this purpose, detailed instructions can be found within.
815
916 Requirements
1017 ------------
1118
1219 * libgd
1320 * sqlite3
14 * LevelDB (optional, set ENABLE_LEVELDB=1 in CMake to enable)
15 * hiredis library (optional, set ENABLE_REDIS=1 in CMake to enable)
16 * Postgres libraries (optional, set ENABLE_POSTGRES=1 in CMake to enable)
21 * LevelDB (optional)
22 * hiredis (optional)
23 * Postgres libraries (optional)
1724
18 e.g. on Debian:
19 ^^^^^^^^^^^^^^^
25 on Debian/Ubuntu:
26 ^^^^^^^^^^^^^^^^^
2027
21 sudo apt-get install libgd-dev libsqlite3-dev libleveldb-dev libhiredis-dev libpq-dev
28 ``sudo apt install libgd-dev libsqlite3-dev libleveldb-dev libhiredis-dev libpq-dev``
2229
23 Windows
24 ^^^^^^^
25 Minetestmapper for Windows can be downloaded here: https://github.com/minetest/minetestmapper/releases
30 on openSUSE:
31 ^^^^^^^^^^^^
2632
27 After extracting the archive, minetestmapper can be invoked from cmd.exe:
33 ``sudo zypper install gd-devel sqlite3-devel leveldb-devel hiredis-devel postgresql-devel``
34
35 for Windows:
36 ^^^^^^^^^^^^
37 Minetestmapper for Windows can be downloaded `from the Releases section
38 <https://github.com/minetest/minetestmapper/releases>`_.
39
40 After extracting the archive, it can be invoked from cmd.exe:
2841 ::
2942
3043 cd C:\Users\yourname\Desktop\example\path
3649 ::
3750
3851 cmake . -DENABLE_LEVELDB=1
39 make -j2
52 make -j$(nproc)
4053
4154 Usage
4255 -----
1212 #include "config.h"
1313 #include "PlayerAttributes.h"
1414 #include "BlockDecoder.h"
15 #include "Image.h"
1516 #include "util.h"
17
1618 #include "db-sqlite3.h"
1719 #if USE_POSTGRESQL
1820 #include "db-postgresql.h"
2325 #if USE_REDIS
2426 #include "db-redis.h"
2527 #endif
26
27 using namespace std;
2828
2929 template<typename T>
3030 static inline T mymax(T a, T b)
5353 static inline unsigned int colorSafeBounds (int channel)
5454 {
5555 return mymin(mymax(channel, 0), 255);
56 }
57
58 static Color parseColor(const std::string &color)
59 {
60 if (color.length() != 7)
61 throw std::runtime_error("Color needs to be 7 characters long");
62 if (color[0] != '#')
63 throw std::runtime_error("Color needs to begin with #");
64 unsigned long col = strtoul(color.c_str() + 1, NULL, 16);
65 u8 b, g, r;
66 b = col & 0xff;
67 g = (col >> 8) & 0xff;
68 r = (col >> 16) & 0xff;
69 return Color(r, g, b);
5670 }
5771
5872 static Color mixColors(Color a, Color b)
97111 m_geomY2(2048),
98112 m_exhaustiveSearch(EXH_AUTO),
99113 m_zoom(1),
100 m_scales(SCALE_LEFT | SCALE_TOP)
114 m_scales(SCALE_LEFT | SCALE_TOP),
115 m_progressMax(0),
116 m_progressLast(-1)
101117 {
102118 }
103119
136152 void TileGenerator::setScales(uint flags)
137153 {
138154 m_scales = flags;
139 }
140
141 Color TileGenerator::parseColor(const std::string &color)
142 {
143 Color parsed;
144 if (color.length() != 7)
145 throw std::runtime_error("Color needs to be 7 characters long");
146 if (color[0] != '#')
147 throw std::runtime_error("Color needs to begin with #");
148 unsigned long col = strtoul(color.c_str() + 1, NULL, 16);
149 parsed.b = col & 0xff;
150 parsed.g = (col >> 8) & 0xff;
151 parsed.r = (col >> 16) & 0xff;
152 parsed.a = 255;
153 return parsed;
154155 }
155156
156157 void TileGenerator::setDrawOrigin(bool drawOrigin)
213214
214215 void TileGenerator::parseColorsFile(const std::string &fileName)
215216 {
216 ifstream in;
217 in.open(fileName.c_str(), ifstream::in);
218 if (!in.is_open())
217 std::ifstream in(fileName);
218 if (!in.good())
219219 throw std::runtime_error("Specified colors file could not be found");
220220 parseColorsStream(in);
221221 }
222222
223223 void TileGenerator::printGeometry(const std::string &input)
224224 {
225 string input_path = input;
225 std::string input_path = input;
226226 if (input_path[input.length() - 1] != PATH_SEPARATOR) {
227227 input_path += PATH_SEPARATOR;
228228 }
248248
249249 void TileGenerator::generate(const std::string &input, const std::string &output)
250250 {
251 string input_path = input;
251 std::string input_path = input;
252252 if (input_path[input.length() - 1] != PATH_SEPARATOR) {
253253 input_path += PATH_SEPARATOR;
254254 }
304304 std::cerr << "Failed to parse color entry '" << line << "'" << std::endl;
305305 continue;
306306 }
307
308 ColorEntry color(r, g, b, a, t);
309 m_colorMap[name] = color;
307
308 m_colorMap[name] = ColorEntry(r, g, b, a, t);
310309 }
311310 }
312311
329328 void TileGenerator::openDb(const std::string &input)
330329 {
331330 std::string backend = m_backend;
332 if(backend == "") {
333 std::ifstream ifs((input + "/world.mt").c_str());
331 if (backend == "") {
332 std::ifstream ifs(input + "/world.mt");
334333 if(!ifs.good())
335 throw std::runtime_error("Failed to read world.mt");
336 backend = read_setting("backend", ifs);
334 throw std::runtime_error("Failed to open world.mt");
335 backend = read_setting_default("backend", ifs, "sqlite3");
337336 ifs.close();
338337 }
339338
356355
357356 // Determine how we're going to traverse the database (heuristic)
358357 if (m_exhaustiveSearch == EXH_AUTO) {
359 using u64 = uint64_t;
360 u64 y_range = (m_yMax / 16 + 1) - (m_yMin / 16);
361 u64 blocks = (u64)(m_geomX2 - m_geomX) * y_range * (u64)(m_geomY2 - m_geomY);
358 size_t y_range = (m_yMax / 16 + 1) - (m_yMin / 16);
359 size_t blocks = (m_geomX2 - m_geomX) * y_range * (m_geomY2 - m_geomY);
362360 #ifndef NDEBUG
363 std::cout << "Heuristic parameters:"
361 std::cerr << "Heuristic parameters:"
364362 << " preferRangeQueries()=" << m_db->preferRangeQueries()
365363 << " y_range=" << y_range << " blocks=" << blocks << std::endl;
366364 #endif
417415 m_positions[pos.z].emplace(pos.x);
418416 }
419417
420 #ifndef NDEBUG
421418 int count = 0;
422419 for (const auto &it : m_positions)
423420 count += it.second.size();
424 std::cout << "Loaded " << count
421 m_progressMax = count;
422 #ifndef NDEBUG
423 std::cerr << "Loaded " << count
425424 << " positions (across Z: " << m_positions.size() << ") for rendering" << std::endl;
426425 #endif
427426 }
475474 {
476475 BlockDecoder blk;
477476 const int16_t yMax = m_yMax / 16 + 1;
477 size_t count = 0;
478478
479479 auto renderSingle = [&] (int16_t xPos, int16_t zPos, BlockList &blockStack) {
480480 m_readPixels.reset();
521521 blockStack.sort();
522522
523523 renderSingle(xPos, zPos, blockStack);
524 reportProgress(count++);
524525 }
525526 postRenderRow(zPos);
526527 }
545546 blockStack.sort();
546547
547548 renderSingle(xPos, zPos, blockStack);
549 reportProgress(count++);
548550 }
549551 postRenderRow(zPos);
550552 }
551553 } else if (m_exhaustiveSearch == EXH_FULL) {
554 const size_t span_y = yMax - (m_yMin / 16);
555 m_progressMax = (m_geomX2 - m_geomX) * span_y * (m_geomY2 - m_geomY);
552556 #ifndef NDEBUG
553557 std::cerr << "Exhaustively searching "
554 << (m_geomX2 - m_geomX) << "x" << (yMax - (m_yMin / 16)) << "x"
558 << (m_geomX2 - m_geomX) << "x" << span_y << "x"
555559 << (m_geomY2 - m_geomY) << " blocks" << std::endl;
556560 #endif
561
557562 std::vector<BlockPos> positions;
558 positions.reserve(yMax - (m_yMin / 16));
563 positions.reserve(span_y);
559564 for (int16_t zPos = m_geomY2 - 1; zPos >= m_geomY; zPos--) {
560565 for (int16_t xPos = m_geomX2 - 1; xPos >= m_geomX; xPos--) {
561566 positions.clear();
567572 blockStack.sort();
568573
569574 renderSingle(xPos, zPos, blockStack);
575 reportProgress(count++);
570576 }
571577 postRenderRow(zPos);
572578 }
573579 }
580
581 reportProgress(m_progressMax);
574582 }
575583
576584 void TileGenerator::renderMapBlock(const BlockDecoder &blk, const BlockPos &pos)
585593 if (m_readPixels.get(x, z))
586594 continue;
587595 int imageX = xBegin + x;
596 auto &attr = m_blockPixelAttributes.attribute(15 - z, xBegin + x);
588597
589598 for (int y = maxY; y >= minY; --y) {
590 string name = blk.getNode(x, y, z);
591 if (name == "")
599 const std::string &name = blk.getNode(x, y, z);
600 if (name.empty())
592601 continue;
593602 ColorMap::const_iterator it = m_colorMap.find(name);
594603 if (it == m_colorMap.end()) {
595604 m_unknownNodes.insert(name);
596605 continue;
597606 }
598 const Color c = it->second.to_color();
607
608 Color c = it->second.toColor();
609 if (c.a == 0)
610 continue; // node is fully invisible
599611 if (m_drawAlpha) {
600 if (m_color[z][x].a == 0)
601 m_color[z][x] = c; // first visible time, no color mixing
602 else
603 m_color[z][x] = mixColors(m_color[z][x], c);
604 if(m_color[z][x].a < 0xff) {
605 // near thickness value to thickness of current node
606 m_thickness[z][x] = (m_thickness[z][x] + it->second.t) / 2.0;
612 if (m_color[z][x].a != 0)
613 c = mixColors(m_color[z][x], c);
614 if (c.a < 255) {
615 // remember color and near thickness value
616 m_color[z][x] = c;
617 m_thickness[z][x] = (m_thickness[z][x] + it->second.t) / 2;
607618 continue;
608619 }
609620 // color became opaque, draw it
610 setZoomed(imageX, imageY, m_color[z][x]);
611 m_blockPixelAttributes.attribute(15 - z, xBegin + x).thickness = m_thickness[z][x];
621 setZoomed(imageX, imageY, c);
622 attr.thickness = m_thickness[z][x];
612623 } else {
613 setZoomed(imageX, imageY, c.noAlpha());
624 c.a = 255;
625 setZoomed(imageX, imageY, c);
614626 }
615627 m_readPixels.set(x, z);
616628
617629 // do this afterwards so we can record height values
618630 // inside transparent nodes (water) too
619631 if (!m_readInfo.get(x, z)) {
620 m_blockPixelAttributes.attribute(15 - z, xBegin + x).height = pos.y * 16 + y;
632 attr.height = pos.y * 16 + y;
621633 m_readInfo.set(x, z);
622634 }
623635 break;
639651 if (m_readPixels.get(x, z))
640652 continue;
641653 int imageX = xBegin + x;
654 auto &attr = m_blockPixelAttributes.attribute(15 - z, xBegin + x);
642655
643656 // set color since it wasn't done in renderMapBlock()
644657 setZoomed(imageX, imageY, m_color[z][x]);
645658 m_readPixels.set(x, z);
646 m_blockPixelAttributes.attribute(15 - z, xBegin + x).thickness = m_thickness[z][x];
659 attr.thickness = m_thickness[z][x];
647660 }
648661 }
649662 }
650663
651664 void TileGenerator::renderShading(int zPos)
652665 {
666 auto &a = m_blockPixelAttributes;
653667 int zBegin = (m_zMax - zPos) * 16;
654668 for (int z = 0; z < 16; ++z) {
655669 int imageY = zBegin + z;
657671 continue;
658672 for (int x = 0; x < m_mapWidth; ++x) {
659673 if(
660 !m_blockPixelAttributes.attribute(z, x).valid_height() ||
661 !m_blockPixelAttributes.attribute(z, x - 1).valid_height() ||
662 !m_blockPixelAttributes.attribute(z - 1, x).valid_height()
674 !a.attribute(z, x).valid_height() ||
675 !a.attribute(z, x - 1).valid_height() ||
676 !a.attribute(z - 1, x).valid_height()
663677 )
664678 continue;
665679
666680 // calculate shadow to apply
667 int y = m_blockPixelAttributes.attribute(z, x).height;
668 int y1 = m_blockPixelAttributes.attribute(z, x - 1).height;
669 int y2 = m_blockPixelAttributes.attribute(z - 1, x).height;
681 int y = a.attribute(z, x).height;
682 int y1 = a.attribute(z, x - 1).height;
683 int y2 = a.attribute(z - 1, x).height;
670684 int d = ((y - y1) + (y - y2)) * 12;
685
671686 if (m_drawAlpha) { // less visible shadow with increasing "thickness"
672 double t = m_blockPixelAttributes.attribute(z, x).thickness * 1.2;
673 d *= 1.0 - mymin(t, 255.0) / 255.0;
674 }
687 float t = a.attribute(z, x).thickness * 1.2f;
688 t = mymin(t, 255.0f);
689 d *= 1.0f - t / 255.0f;
690 }
691
675692 d = mymin(d, 36);
676693
694 // apply shadow/light by just adding to it pixel values
677695 Color c = m_image->getPixel(getImageX(x), getImageY(imageY));
678696 c.r = colorSafeBounds(c.r + d);
679697 c.g = colorSafeBounds(c.g + d);
681699 setZoomed(x, imageY, c);
682700 }
683701 }
684 m_blockPixelAttributes.scroll();
702 a.scroll();
685703 }
686704
687705 void TileGenerator::renderScale()
793811 std::cerr << "\t" << node << std::endl;
794812 }
795813
814 void TileGenerator::reportProgress(size_t count)
815 {
816 if (!m_progressMax)
817 return;
818 int percent = count / static_cast<float>(m_progressMax) * 100;
819 if (percent == m_progressLast)
820 return;
821 m_progressLast = percent;
822
823 // Print a nice-looking ASCII progress bar
824 char bar[51] = {0};
825 memset(bar, ' ', 50);
826 int i = 0, j = percent;
827 for (; j >= 2; j -= 2)
828 bar[i++] = '=';
829 if (j)
830 bar[i++] = '-';
831 std::cout << "[" << bar << "] " << percent << "% " << (percent == 100 ? "\n" : "\r");
832 std::cout.flush();
833 }
834
796835 inline int TileGenerator::getImageX(int val, bool absolute) const
797836 {
798837 if (absolute)
0 /*
1 * =====================================================================
2 * Version: 1.0
3 * Created: 18.09.2012 10:20:47
4 * Author: Miroslav Bendík
5 * Company: LinuxOS.sk
6 * =====================================================================
7 */
8
90 #include <zlib.h>
101 #include <stdint.h>
112 #include "ZlibDecompressor.h"
3728 const std::size_t size = m_size - m_seekPos;
3829
3930 ustring buffer;
40 const size_t BUFSIZE = 128 * 1024;
41 uint8_t temp_buffer[BUFSIZE];
31 constexpr size_t BUFSIZE = 128 * 1024;
32 unsigned char temp_buffer[BUFSIZE];
4233
4334 z_stream strm;
4435 strm.zalloc = Z_NULL;
4738 strm.next_in = Z_NULL;
4839 strm.avail_in = size;
4940
50 if (inflateInit(&strm) != Z_OK) {
41 if (inflateInit(&strm) != Z_OK)
5142 throw DecompressError();
52 }
5343
5444 strm.next_in = const_cast<unsigned char *>(data);
5545 int ret = 0;
5747 strm.avail_out = BUFSIZE;
5848 strm.next_out = temp_buffer;
5949 ret = inflate(&strm, Z_NO_FLUSH);
60 buffer += ustring(reinterpret_cast<unsigned char *>(temp_buffer), BUFSIZE - strm.avail_out);
50 buffer.append(temp_buffer, BUFSIZE - strm.avail_out);
6151 } while (ret == Z_OK);
62 if (ret != Z_STREAM_END) {
52 if (ret != Z_STREAM_END)
6353 throw DecompressError();
64 }
54
6555 m_seekPos += strm.next_in - data;
6656 (void)inflateEnd(&strm);
6757
0 #include <zstd.h>
1 #include "ZstdDecompressor.h"
2
3 ZstdDecompressor::ZstdDecompressor():
4 m_data(nullptr),
5 m_seekPos(0),
6 m_size(0)
7 {
8 m_stream = ZSTD_createDStream();
9 }
10
11 ZstdDecompressor::~ZstdDecompressor()
12 {
13 ZSTD_freeDStream(reinterpret_cast<ZSTD_DStream*>(m_stream));
14 }
15
16 void ZstdDecompressor::setData(const u8 *data, size_t size, size_t seekPos)
17 {
18 m_data = data;
19 m_seekPos = seekPos;
20 m_size = size;
21 }
22
23 std::size_t ZstdDecompressor::seekPos() const
24 {
25 return m_seekPos;
26 }
27
28 ustring ZstdDecompressor::decompress()
29 {
30 ZSTD_DStream *stream = reinterpret_cast<ZSTD_DStream*>(m_stream);
31 ZSTD_inBuffer inbuf = { m_data, m_size, m_seekPos };
32
33 ustring buffer;
34 constexpr size_t BUFSIZE = 32 * 1024;
35
36 buffer.resize(BUFSIZE);
37 ZSTD_outBuffer outbuf = { &buffer[0], buffer.size(), 0 };
38
39 ZSTD_initDStream(stream);
40
41 size_t ret;
42 do {
43 ret = ZSTD_decompressStream(stream, &outbuf, &inbuf);
44 if (outbuf.size == outbuf.pos) {
45 outbuf.size += BUFSIZE;
46 buffer.resize(outbuf.size);
47 outbuf.dst = &buffer[0];
48 }
49 if (ret && ZSTD_isError(ret))
50 throw DecompressError();
51 } while (ret != 0);
52
53 m_seekPos = inbuf.pos;
54 buffer.resize(outbuf.pos);
55
56 return buffer;
57 }
+0
-132
autogenerating-colors.txt less more
0 ==FILE== mods/dumpnodes/init.lua
1 local function nd_get_tiles(nd)
2 return nd.tiles or nd.tile_images
3 end
4
5 local function nd_get_tile(nd, n)
6 local tile = nd_get_tiles(nd)[n]
7 if type(tile) == 'table' then
8 tile = tile.name
9 end
10 return tile
11 end
12
13 local function pairs_s(dict)
14 local keys = {}
15 for k in pairs(dict) do
16 table.insert(keys, k)
17 end
18 table.sort(keys)
19 return ipairs(keys)
20 end
21
22 minetest.register_chatcommand("dumpnodes", {
23 params = "",
24 description = "",
25 func = function(player, param)
26 local n = 0
27 local ntbl = {}
28 for _, nn in pairs_s(minetest.registered_nodes) do
29 local nd = minetest.registered_nodes[nn]
30 local prefix, name = nn:match('(.*):(.*)')
31 if prefix == nil or name == nil then
32 print("ignored(1): " .. nn)
33 else
34 if ntbl[prefix] == nil then
35 ntbl[prefix] = {}
36 end
37 ntbl[prefix][name] = true
38 end
39 end
40 local out, err = io.open('nodes.txt', 'wb')
41 if not out then
42 return true, "io.open(): " .. err
43 end
44 for _, prefix in pairs_s(ntbl) do
45 out:write('# ' .. prefix .. '\n')
46 for _, name in pairs_s(ntbl[prefix]) do
47 local nn = prefix .. ":" .. name
48 local nd = minetest.registered_nodes[nn]
49 if nd.drawtype == 'airlike' or nd_get_tiles(nd) == nil then
50 print("ignored(2): " .. nn)
51 else
52 local tl = nd_get_tile(nd, 1)
53 tl = (tl .. '^'):match('(.-)^') -- strip modifiers
54 out:write(nn .. ' ' .. tl .. '\n')
55 n = n + 1
56 end
57 end
58 out:write('\n')
59 end
60 out:close()
61 return true, n .. " nodes dumped."
62 end,
63 })
64 ==FILE== avgcolor.py
65 #!/usr/bin/env python
66 import sys
67 from math import sqrt
68 from PIL import Image
69
70 if len(sys.argv) < 2:
71 print("Prints average color (RGB) of input image")
72 print("Usage: %s <input>" % sys.argv[0])
73 exit(1)
74
75 inp = Image.open(sys.argv[1]).convert('RGBA')
76 ind = inp.load()
77
78 cl = ([], [], [])
79 for x in range(inp.size[0]):
80 for y in range(inp.size[1]):
81 px = ind[x, y]
82 if px[3] < 128: continue # alpha
83 cl[0].append(px[0]**2)
84 cl[1].append(px[1]**2)
85 cl[2].append(px[2]**2)
86
87 if len(cl[0]) == 0:
88 print("Didn't find average color for %s" % sys.argv[1], file=sys.stderr)
89 print("0 0 0")
90 else:
91 cl = tuple(sqrt(sum(x)/len(x)) for x in cl)
92 print("%d %d %d" % cl)
93 ==SCRIPT==
94 #!/bin/bash -e
95 AVGCOLOR_PATH=/path/to/avgcolor.py
96 GAME_PATH=/path/to/minetest_game
97 MODS_PATH= # path to "mods" folder, only set if you have loaded mods
98 NODESTXT_PATH=./nodes.txt
99 COLORSTXT_PATH=./colors.txt
100
101 while read -r line; do
102 set -- junk $line; shift
103 if [[ -z "$1" || $1 == "#" ]]; then
104 echo "$line"; continue
105 fi
106 tex=$(find $GAME_PATH -type f -name "$2")
107 [[ -z "$tex" && -n "$MODS_PATH" ]] && tex=$(find $MODS_PATH -type f -name "$2")
108 if [ -z "$tex" ]; then
109 echo "skip $1: texture not found" >&2
110 continue
111 fi
112 echo "$1" $(python $AVGCOLOR_PATH "$tex")
113 echo "ok $1" >&2
114 done < $NODESTXT_PATH > $COLORSTXT_PATH
115 # Use nicer colors for water and lava:
116 sed -re 's/^default:((river_)?water_(flowing|source)) [0-9 ]+$/default:\1 39 66 106 128 224/g' $COLORSTXT_PATH -i
117 sed -re 's/^default:(lava_(flowing|source)) [0-9 ]+$/default:\1 255 100 0/g' $COLORSTXT_PATH -i
118 # Add transparency to glass nodes and xpanes:
119 sed -re 's/^default:(.*glass) ([0-9 ]+)$/default:\1 \2 64 16/g' $COLORSTXT_PATH -i
120 sed -re 's/^doors:(.*glass[^ ]*) ([0-9 ]+)$/doors:\1 \2 64 16/g' $COLORSTXT_PATH -i
121 sed -re 's/^xpanes:(.*(pane|bar)[^ ]*) ([0-9 ]+)$/xpanes:\1 \3 64 16/g' $COLORSTXT_PATH -i
122 # Delete some usually hidden nodes:
123 sed '/^doors:hidden /d' $COLORSTXT_PATH -i
124 sed '/^fireflies:firefly /d' $COLORSTXT_PATH -i
125 sed '/^butterflies:butterfly_/d' $COLORSTXT_PATH -i
126 ==INSTRUCTIONS==
127 1) Make sure avgcolors.py works (outputs the usage instructions when run)
128 2) Add the dumpnodes mod to Minetest
129 3) Create a world and load dumpnodes & all mods you want to generate colors for
130 4) Execute /dumpnodes ingame
131 5) Run the script to generate colors.txt (make sure to adjust the PATH variables at the top)
0 mark_as_advanced(ZSTD_LIBRARY ZSTD_INCLUDE_DIR)
1
2 find_path(ZSTD_INCLUDE_DIR NAMES zstd.h)
3
4 find_library(ZSTD_LIBRARY NAMES zstd)
5
6 if(ZSTD_INCLUDE_DIR AND ZSTD_LIBRARY)
7 # Check that the API we use exists
8 include(CheckSymbolExists)
9 unset(HAVE_ZSTD_INITDSTREAM CACHE)
10 set(CMAKE_REQUIRED_INCLUDES ${ZSTD_INCLUDE_DIR})
11 set(CMAKE_REQUIRED_LIBRARIES ${ZSTD_LIBRARY})
12 check_symbol_exists(ZSTD_initDStream zstd.h HAVE_ZSTD_INITDSTREAM)
13 unset(CMAKE_REQUIRED_INCLUDES)
14 unset(CMAKE_REQUIRED_LIBRARIES)
15
16 if(NOT HAVE_ZSTD_INITDSTREAM)
17 unset(ZSTD_INCLUDE_DIR CACHE)
18 unset(ZSTD_LIBRARY CACHE)
19 endif()
20 endif()
21
22 include(FindPackageHandleStandardArgs)
23 find_package_handle_standard_args(Zstd DEFAULT_MSG ZSTD_LIBRARY ZSTD_INCLUDE_DIR)
0 minetestmapper (20200328+git20210911.1.0198897-1) UNRELEASED; urgency=low
1
2 * New upstream snapshot.
3
4 -- Debian Janitor <janitor@jelmer.uk> Tue, 09 Nov 2021 12:02:16 -0000
5
06 minetestmapper (20200328-1) unstable; urgency=medium
17
28 * New upstream release.
0 #ifndef BLOCKDECODER_H
1 #define BLOCKDECODER_H
0 #pragma once
21
2 #include <cstdint>
33 #include <unordered_map>
4
54 #include "types.h"
5 #include <ZstdDecompressor.h>
66
77 class BlockDecoder {
88 public:
1111 void reset();
1212 void decode(const ustring &data);
1313 bool isEmpty() const;
14 std::string getNode(u8 x, u8 y, u8 z) const; // returns "" for air, ignore and invalid nodes
14 // returns "" for air, ignore and invalid nodes
15 const std::string &getNode(u8 x, u8 y, u8 z) const;
1516
1617 private:
17 typedef std::unordered_map<int, std::string> NameMap;
18 typedef std::unordered_map<uint16_t, std::string> NameMap;
1819 NameMap m_nameMap;
19 int m_blockAirId;
20 int m_blockIgnoreId;
20 uint16_t m_blockAirId, m_blockIgnoreId;
2121
22 u8 m_version;
22 u8 m_version, m_contentWidth;
2323 ustring m_mapData;
24
25 // one instance for performance
26 ZstdDecompressor m_zstd_decompressor;
2427 };
25
26 #endif // BLOCKDECODER_H
0 #ifndef IMAGE_HEADER
1 #define IMAGE_HEADER
0 #pragma once
21
32 #include "types.h"
43 #include <string>
87 Color() : r(0), g(0), b(0), a(0) {};
98 Color(u8 r, u8 g, u8 b) : r(r), g(g), b(b), a(255) {};
109 Color(u8 r, u8 g, u8 b, u8 a) : r(r), g(g), b(b), a(a) {};
11 inline Color noAlpha() const { return Color(r, g, b); }
1210
1311 u8 r, g, b, a;
1412 };
1715 public:
1816 Image(int width, int height);
1917 ~Image();
18
19 Image(const Image&) = delete;
20 Image& operator=(const Image&) = delete;
2021
2122 void setPixel(int x, int y, const Color &c);
2223 Color getPixel(int x, int y);
2728 void save(const std::string &filename);
2829
2930 private:
30 Image(const Image&);
31
3231 int m_width, m_height;
3332 gdImagePtr m_image;
3433 };
35
36 #endif // IMAGE_HEADER
0 /*
1 * =====================================================================
2 * Version: 1.0
3 * Created: 25.08.2012 10:55:29
4 * Author: Miroslav Bendík
5 * Company: LinuxOS.sk
6 * =====================================================================
7 */
0 #pragma once
81
9 #ifndef PIXELATTRIBUTES_H_ADZ35GYF
10 #define PIXELATTRIBUTES_H_ADZ35GYF
11
12 #include <limits>
13 #include <stdint.h>
2 #include <climits>
3 #include <cstdint>
144 #include "config.h"
155
166 struct PixelAttribute {
17 PixelAttribute(): height(std::numeric_limits<int>::min()), thickness(0) {};
18 int height;
7 PixelAttribute(): height(INT16_MIN), thickness(0) {};
8 int16_t height;
199 uint8_t thickness;
2010 inline bool valid_height() {
21 return height != std::numeric_limits<int>::min();
11 return height != INT16_MIN;
2212 }
2313 };
2414
2919 virtual ~PixelAttributes();
3020 void setWidth(int width);
3121 void scroll();
32 inline PixelAttribute &attribute(int z, int x) { return m_pixelAttributes[z + 1][x + 1]; };
22 inline PixelAttribute &attribute(int z, int x) {
23 return m_pixelAttributes[z + 1][x + 1];
24 };
3325
3426 private:
3527 void freeAttributes();
4436 PixelAttribute *m_pixelAttributes[BLOCK_SIZE + 2]; // 1px gradient + empty
4537 int m_width;
4638 };
47
48 #endif /* end of include guard: PIXELATTRIBUTES_H_ADZ35GYF */
49
0 #ifndef PLAYERATTRIBUTES_H_D7THWFVV
1 #define PLAYERATTRIBUTES_H_D7THWFVV
0 #pragma once
21
32 #include <list>
43 #include <string>
1514 typedef std::list<Player> Players;
1615
1716 PlayerAttributes(const std::string &worldDir);
18 Players::iterator begin();
19 Players::iterator end();
17 Players::const_iterator begin() const;
18 Players::const_iterator end() const;
2019
2120 private:
2221 void readFiles(const std::string &playersPath);
2423
2524 Players m_players;
2625 };
27
28 #endif /* end of include guard: PLAYERATTRIBUTES_H_D7THWFVV */
29
0 #ifndef TILEGENERATOR_HEADER
1 #define TILEGENERATOR_HEADER
0 #pragma once
21
3 #include <iosfwd>
2 #include <iostream>
43 #include <map>
54 #include <set>
6 #include <config.h>
75 #include <unordered_map>
86 #include <unordered_set>
9 #include <stdint.h>
7 #include <cstdint>
108 #include <string>
119
1210 #include "PixelAttributes.h"
13 #include "BlockDecoder.h"
1411 #include "Image.h"
1512 #include "db.h"
1613 #include "types.h"
14
15 class BlockDecoder;
16 class Image;
1717
1818 enum {
1919 SCALE_TOP = (1 << 0),
3030 };
3131
3232 struct ColorEntry {
33 ColorEntry(): r(0), g(0), b(0), a(0), t(0) {};
34 ColorEntry(uint8_t r, uint8_t g, uint8_t b, uint8_t a, uint8_t t): r(r), g(g), b(b), a(a), t(t) {};
35 inline Color to_color() const { return Color(r, g, b, a); }
36 uint8_t r, g, b, a, t;
33 ColorEntry() : r(0), g(0), b(0), a(0), t(0) {};
34 ColorEntry(uint8_t r, uint8_t g, uint8_t b, uint8_t a, uint8_t t) :
35 r(r), g(g), b(b), a(a), t(t) {};
36 inline Color toColor() const { return Color(r, g, b, a); }
37 uint8_t r, g, b, a; // Red, Green, Blue, Alpha
38 uint8_t t; // "thickness" value
3739 };
3840
3941 struct BitmapThing { // 16x16 bitmap
7274 void setScaleColor(const std::string &scaleColor);
7375 void setOriginColor(const std::string &originColor);
7476 void setPlayerColor(const std::string &playerColor);
75 Color parseColor(const std::string &color);
7677 void setDrawOrigin(bool drawOrigin);
7778 void setDrawPlayers(bool drawPlayers);
7879 void setDrawScale(bool drawScale);
107108 void renderPlayers(const std::string &inputPath);
108109 void writeImage(const std::string &output);
109110 void printUnknown();
111 void reportProgress(size_t count);
110112 int getImageX(int val, bool absolute=false) const;
111113 int getImageY(int val, bool absolute=false) const;
112114 void setZoomed(int x, int y, Color color);
141143 int16_t m_geomY; /* Y in terms of rendered image, Z in the world */
142144 int16_t m_geomX2;
143145 int16_t m_geomY2;
144 /* */
146
145147 int m_mapWidth;
146148 int m_mapHeight;
147149 int m_exhaustiveSearch;
155157
156158 int m_zoom;
157159 uint m_scales;
160
161 size_t m_progressMax;
162 int m_progressLast; // percentage
158163 }; // class TileGenerator
159
160 #endif // TILEGENERATOR_HEADER
0 /*
1 * =====================================================================
2 * Version: 1.0
3 * Created: 18.09.2012 10:20:51
4 * Author: Miroslav Bendík
5 * Company: LinuxOS.sk
6 * =====================================================================
7 */
8
9 #ifndef ZLIBDECOMPRESSOR_H_ZQL1PN8Q
10 #define ZLIBDECOMPRESSOR_H_ZQL1PN8Q
0 #pragma once
111
122 #include <cstdlib>
133 #include <string>
3020 const unsigned char *m_data;
3121 std::size_t m_seekPos;
3222 std::size_t m_size;
33 }; /* ----- end of class ZlibDecompressor ----- */
34
35 #endif /* end of include guard: ZLIBDECOMPRESSOR_H_ZQL1PN8Q */
36
23 };
0 #pragma once
1
2 #include <cstdlib>
3 #include <string>
4 #include "types.h"
5
6 class ZstdDecompressor
7 {
8 public:
9 class DecompressError {};
10
11 ZstdDecompressor();
12 ~ZstdDecompressor();
13 void setData(const u8 *data, size_t size, size_t seekPos);
14 size_t seekPos() const;
15 ustring decompress();
16
17 private:
18 void *m_stream; // ZSTD_DStream
19 const u8 *m_data;
20 size_t m_seekPos, m_size;
21 };
0 #ifndef DB_LEVELDB_HEADER
1 #define DB_LEVELDB_HEADER
0 #pragma once
21
32 #include "db.h"
43 #include <unordered_map>
2625 std::unordered_map<int16_t, std::vector<pos2d>> posCache;
2726 leveldb::DB *db;
2827 };
29
30 #endif // DB_LEVELDB_HEADER
0 #ifndef _DB_POSTGRESQL_H
1 #define _DB_POSTGRESQL_H
0 #pragma once
21
32 #include "db.h"
43 #include <libpq-fe.h>
3029 private:
3130 PGconn *db;
3231 };
33
34 #endif // _DB_POSTGRESQL_H
0 #ifndef DB_REDIS_HEADER
1 #define DB_REDIS_HEADER
0 #pragma once
21
32 #include "db.h"
43 #include <unordered_map>
3231 redisContext *ctx;
3332 std::string hash;
3433 };
35
36 #endif // DB_REDIS_HEADER
0 #ifndef _DB_SQLITE3_H
1 #define _DB_SQLITE3_H
0 #pragma once
21
32 #include "db.h"
43 #include <unordered_map>
3130 int16_t blockCachedZ = -10000;
3231 std::unordered_map<int16_t, BlockList> blockCache; // indexed by X
3332 };
34
35 #endif // _DB_SQLITE3_H
0 #ifndef DB_HEADER
1 #define DB_HEADER
0 #pragma once
21
3 #include <stdint.h>
4 #include <map>
2 #include <cstdint>
53 #include <list>
64 #include <vector>
75 #include <utility>
121119 * End black magic *
122120 *******************/
123121
124 #endif // DB_HEADER
0 #ifndef UTIL_H
1 #define UTIL_H
0 #pragma once
21
32 #include <string>
43 #include <fstream>
54
65 std::string read_setting(const std::string &name, std::istream &is);
76
8 inline std::string read_setting_default(const std::string &name, std::istream &is, const std::string &def)
9 {
10 try {
11 return read_setting(name, is);
12 } catch(const std::runtime_error &e) {
13 return def;
14 }
15 }
16
17 #endif // UTIL_H
7 std::string read_setting_default(const std::string &name, std::istream &is,
8 const std::string &def);
77 #include <string>
88 #include <sstream>
99 #include <stdexcept>
10 #include "cmake_config.h"
10 #include "config.h"
1111 #include "TileGenerator.h"
1212
1313 static void usage()
5757
5858 static bool file_exists(const std::string &path)
5959 {
60 std::ifstream ifs(path.c_str());
60 std::ifstream ifs(path);
6161 return ifs.is_open();
6262 }
6363
255255 generator.parseColorsFile(colors);
256256 generator.generate(input, output);
257257
258 } catch(std::runtime_error &e) {
258 } catch (const std::runtime_error &e) {
259259 std::cerr << "Exception: " << e.what() << std::endl;
260260 return 1;
261261 }
0 #!/bin/bash -e
1
2 [ -z "$CXX" ] && exit 255
3 export CC=false # don't need it actually
4
5 variant=win32
6 [[ "$(basename "$CXX")" == "x86_64-"* ]] && variant=win64
7
8 #######
9 # this expects unpacked libraries similar to what Minetest's buildbot uses
10 # $extradlls will typically point to the DLLs for libgcc, libstdc++ and libpng
11 libgd_dir=
12 zlib_dir=
13 zstd_dir=
14 sqlite_dir=
15 leveldb_dir=
16 extradlls=()
17 #######
18
19 [ -f ./CMakeLists.txt ] || exit 1
20
21 cmake -S . -B build \
22 -DCMAKE_SYSTEM_NAME=Windows \
23 -DCMAKE_EXE_LINKER_FLAGS="-s" \
24 \
25 -DENABLE_LEVELDB=1 \
26 \
27 -DLEVELDB_INCLUDE_DIR=$leveldb_dir/include \
28 -DLEVELDB_LIBRARY=$leveldb_dir/lib/libleveldb.dll.a \
29 -DLIBGD_INCLUDE_DIR=$libgd_dir/include \
30 -DLIBGD_LIBRARY=$libgd_dir/lib/libgd.dll.a \
31 -DSQLITE3_INCLUDE_DIR=$sqlite_dir/include \
32 -DSQLITE3_LIBRARY=$sqlite_dir/lib/libsqlite3.dll.a \
33 -DZLIB_INCLUDE_DIR=$zlib_dir/include \
34 -DZLIB_LIBRARY=$zlib_dir/lib/libz.dll.a \
35 -DZSTD_INCLUDE_DIR=$zstd_dir/include \
36 -DZSTD_LIBRARY=$zstd_dir/lib/libzstd.dll.a \
37
38 make -C build -j4
39
40 mkdir pack
41 cp -p \
42 AUTHORS colors.txt COPYING README.rst \
43 build/minetestmapper.exe \
44 $leveldb_dir/bin/libleveldb.dll \
45 $libgd_dir/bin/libgd*.dll \
46 $sqlite_dir/bin/libsqlite*.dll \
47 $zlib_dir/bin/zlib1.dll \
48 $zstd_dir/bin/libzstd.dll \
49 "${extradlls[@]}" \
50 pack/
51 zipfile=$PWD/minetestmapper-$variant.zip
52 (cd pack; zip -9r "$zipfile" *)
53
54 rm -rf build pack
55 echo "Done."
+0
-73
util/build_win.sh less more
0 #!/bin/bash -e
1
2 #######
3 # this expects an env similar to what minetest's buildbot uses
4 # extradll_path will typically contain libgcc, libstdc++ and libpng
5 toolchain_file=
6 toolchain_file64=
7 libgd_dir=
8 libgd_dir64=
9 zlib_dir=
10 zlib_dir64=
11 sqlite_dir=
12 sqlite_dir64=
13 leveldb_dir=
14 leveldb_dir64=
15 extradll_path=
16 extradll_path64=
17 #######
18
19 [ -f ./CMakeLists.txt ] || exit 1
20
21 if [ "$1" == "32" ]; then
22 :
23 elif [ "$1" == "64" ]; then
24 toolchain_file=$toolchain_file64
25 libgd_dir=$libgd_dir64
26 zlib_dir=$zlib_dir64
27 sqlite_dir=$sqlite_dir64
28 leveldb_dir=$leveldb_dir64
29 extradll_path=$extradll_path64
30 else
31 echo "Usage: $0 <32 / 64>"
32 exit 1
33 fi
34
35 cmake . \
36 -DCMAKE_INSTALL_PREFIX=/tmp \
37 -DCMAKE_TOOLCHAIN_FILE=$toolchain_file \
38 -DCMAKE_EXE_LINKER_FLAGS="-s" \
39 \
40 -DENABLE_LEVELDB=1 \
41 \
42 -DLIBGD_INCLUDE_DIR=$libgd_dir/include \
43 -DLIBGD_LIBRARY=$libgd_dir/lib/libgd.dll.a \
44 \
45 -DZLIB_INCLUDE_DIR=$zlib_dir/include \
46 -DZLIB_LIBRARY=$zlib_dir/lib/libz.dll.a \
47 \
48 -DSQLITE3_INCLUDE_DIR=$sqlite_dir/include \
49 -DSQLITE3_LIBRARY=$sqlite_dir/lib/libsqlite3.dll.a \
50 \
51 -DLEVELDB_INCLUDE_DIR=$leveldb_dir/include \
52 -DLEVELDB_LIBRARY=$leveldb_dir/lib/libleveldb.dll.a
53
54 make -j4
55
56 mkdir pack
57 cp -p \
58 AUTHORS colors.txt COPYING README.rst \
59 minetestmapper.exe \
60 $libgd_dir/bin/libgd-3.dll \
61 $zlib_dir/bin/zlib1.dll \
62 $sqlite_dir/bin/libsqlite3-0.dll \
63 $leveldb_dir/bin/libleveldb.dll \
64 $extradll_path/*.dll \
65 pack/
66 zipfile=minetestmapper-win$1.zip
67 (cd pack; zip -9r ../$zipfile *)
68
69 make clean
70 rm -r pack CMakeCache.txt
71
72 echo "Done."
0 #!/bin/bash -e
1
2 install_linux_deps() {
3 local pkgs=(cmake libgd-dev libsqlite3-dev libleveldb-dev libpq-dev libhiredis-dev libzstd-dev)
4
5 sudo apt-get update
6 sudo apt-get install -y --no-install-recommends ${pkgs[@]} "$@"
7 }
8
9 run_build() {
10 cmake . -DCMAKE_BUILD_TYPE=Debug \
11 -DENABLE_LEVELDB=1 -DENABLE_POSTGRESQL=1 -DENABLE_REDIS=1
12
13 make -j2
14 }
15
16 do_functional_test() {
17 mkdir testmap
18 echo "backend = sqlite3" >testmap/world.mt
19 sqlite3 testmap/map.sqlite <<END
20 CREATE TABLE blocks(pos INT,data BLOB);
21 INSERT INTO blocks(pos, data) VALUES(0, x'$(cat util/ci/test_block)');
22 END
23
24 ./minetestmapper --noemptyimage -i ./testmap -o map.png
25 file map.png
26 }
0 1b00ffff020278daedd4c1090000080331dd7f691710faf12589235cb12ae870fca6bffefaebafbffefaebafbffefaebbff7b708fdf1ffd11ffdd11ffdd11ffd01000000000000003836d59f010578da63000000010001000000ffffffff000002000000036169720001000d64656661756c743a73746f6e650a0000
0 local function get_tile(tiles, n)
1 local tile = tiles[n]
2 if type(tile) == 'table' then
3 return tile.name
4 end
5 return tile
6 end
7
8 local function pairs_s(dict)
9 local keys = {}
10 for k in pairs(dict) do
11 keys[#keys+1] = k
12 end
13 table.sort(keys)
14 return ipairs(keys)
15 end
16
17 minetest.register_chatcommand("dumpnodes", {
18 description = "Dump node and texture list for use with minetestmapper",
19 func = function()
20 local ntbl = {}
21 for _, nn in pairs_s(minetest.registered_nodes) do
22 local prefix, name = nn:match('(.*):(.*)')
23 if prefix == nil or name == nil then
24 print("ignored(1): " .. nn)
25 else
26 if ntbl[prefix] == nil then
27 ntbl[prefix] = {}
28 end
29 ntbl[prefix][name] = true
30 end
31 end
32 local out, err = io.open(minetest.get_worldpath() .. "/nodes.txt", 'wb')
33 if not out then
34 return true, err
35 end
36 local n = 0
37 for _, prefix in pairs_s(ntbl) do
38 out:write('# ' .. prefix .. '\n')
39 for _, name in pairs_s(ntbl[prefix]) do
40 local nn = prefix .. ":" .. name
41 local nd = minetest.registered_nodes[nn]
42 local tiles = nd.tiles or nd.tile_images
43 if tiles == nil or nd.drawtype == 'airlike' then
44 print("ignored(2): " .. nn)
45 else
46 local tex = get_tile(tiles, 1)
47 tex = (tex .. '^'):match('%(*(.-)%)*^') -- strip modifiers
48 if tex:find("[combine", 1, true) then
49 tex = tex:match('.-=([^:]-)') -- extract first texture
50 end
51 out:write(nn .. ' ' .. tex .. '\n')
52 n = n + 1
53 end
54 end
55 out:write('\n')
56 end
57 out:close()
58 return true, n .. " nodes dumped."
59 end,
60 })
0 name = dumpnodes
1 description = minetestmapper development mod (node dumper)
0 #!/usr/bin/env python3
1 import sys
2 import os.path
3 import getopt
4 import re
5 from math import sqrt
6 try:
7 from PIL import Image
8 except:
9 print("Could not load image routines, install PIL ('pillow' on pypi)!", file=sys.stderr)
10 exit(1)
11
12 ############
13 ############
14 # Instructions for generating a colors.txt file for custom games and/or mods:
15 # 1) Add the dumpnodes mod to a Minetest world with the chosen game and mods enabled.
16 # 2) Join ingame and run the /dumpnodes chat command.
17 # 3) Run this script and poin it to the installation path of the game using -g,
18 # the path(s) where mods are stored using -m and the nodes.txt in your world folder.
19 # Example command line:
20 # ./util/generate_colorstxt.py --game /usr/share/minetest/games/minetest_game \
21 # -m ~/.minetest/mods ~/.minetest/worlds/my_world/nodes.txt
22 # 4) Copy the resulting colors.txt file to your world folder or to any other places
23 # and use it with minetestmapper's --colors option.
24 ###########
25 ###########
26
27 # minimal sed syntax, s|match|replace| and /match/d supported
28 REPLACEMENTS = [
29 # Delete some nodes that are usually hidden
30 r'/^fireflies:firefly /d',
31 r'/^butterflies:butterfly_/d',
32 # Nicer colors for water and lava
33 r's/^(default:(river_)?water_(flowing|source)) [0-9 ]+$/\1 39 66 106 128 224/',
34 r's/^(default:lava_(flowing|source)) [0-9 ]+$/\1 255 100 0/',
35 # Transparency for glass nodes and panes
36 r's/^(default:.*glass) ([0-9 ]+)$/\1 \2 64 16/',
37 r's/^(doors:.*glass[^ ]*) ([0-9 ]+)$/\1 \2 64 16/',
38 r's/^(xpanes:.*(pane|bar)[^ ]*) ([0-9 ]+)$/\1 \3 64 16/',
39 ]
40
41 def usage():
42 print("Usage: generate_colorstxt.py [options] [input file] [output file]")
43 print("If not specified the input file defaults to ./nodes.txt and the output file to ./colors.txt")
44 print(" -g / --game <folder>\t\tSet path to the game (for textures), required")
45 print(" -m / --mods <folder>\t\tAdd search path for mod textures")
46 print(" --replace <file>\t\tLoad replacements from file (ADVANCED)")
47
48 def collect_files(path):
49 dirs = []
50 with os.scandir(path) as it:
51 for entry in it:
52 if entry.name[0] == '.': continue
53 if entry.is_dir():
54 dirs.append(entry.path)
55 continue
56 if entry.is_file() and '.' in entry.name:
57 if entry.name not in textures.keys():
58 textures[entry.name] = entry.path
59 for path2 in dirs:
60 collect_files(path2)
61
62 def average_color(filename):
63 inp = Image.open(filename).convert('RGBA')
64 data = inp.load()
65
66 c0, c1, c2 = [], [], []
67 for x in range(inp.size[0]):
68 for y in range(inp.size[1]):
69 px = data[x, y]
70 if px[3] < 128: continue # alpha
71 c0.append(px[0]**2)
72 c1.append(px[1]**2)
73 c2.append(px[2]**2)
74
75 if len(c0) == 0:
76 print(f"didn't find color for '{os.path.basename(filename)}'", file=sys.stderr)
77 return "0 0 0"
78 c0 = sqrt(sum(c0) / len(c0))
79 c1 = sqrt(sum(c1) / len(c1))
80 c2 = sqrt(sum(c2) / len(c2))
81 return "%d %d %d" % (c0, c1, c2)
82
83 def apply_sed(line, exprs):
84 for expr in exprs:
85 if expr[0] == '/':
86 if not expr.endswith("/d"): raise ValueError()
87 if re.search(expr[1:-2], line):
88 return ''
89 elif expr[0] == 's':
90 expr = expr.split(expr[1])
91 if len(expr) != 4 or expr[3] != '': raise ValueError()
92 line = re.sub(expr[1], expr[2], line)
93 else:
94 raise ValueError()
95 return line
96 #
97
98 try:
99 opts, args = getopt.getopt(sys.argv[1:], "hg:m:", ["help", "game=", "mods=", "replace="])
100 except getopt.GetoptError as e:
101 print(str(e))
102 exit(1)
103 if ('-h', '') in opts or ('--help', '') in opts:
104 usage()
105 exit(0)
106
107 input_file = "./nodes.txt"
108 output_file = "./colors.txt"
109 texturepaths = []
110
111 try:
112 gamepath = next(o[1] for o in opts if o[0] in ('-g', '--game'))
113 if not os.path.isdir(os.path.join(gamepath, "mods")):
114 print(f"'{gamepath}' doesn't exist or does not contain a game.", file=sys.stderr)
115 exit(1)
116 texturepaths.append(os.path.join(gamepath, "mods"))
117 except StopIteration:
118 print("No game path set but one is required. (see --help)", file=sys.stderr)
119 exit(1)
120
121 try:
122 tmp = next(o[1] for o in opts if o[0] == "--replace")
123 REPLACEMENTS.clear()
124 with open(tmp, 'r') as f:
125 for line in f:
126 if not line or line[0] == '#': continue
127 REPLACEMENTS.append(line.strip())
128 except StopIteration:
129 pass
130
131 for o in opts:
132 if o[0] not in ('-m', '--mods'): continue
133 if not os.path.isdir(o[1]):
134 print(f"Given path '{o[1]}' does not exist.'", file=sys.stderr)
135 exit(1)
136 texturepaths.append(o[1])
137
138 if len(args) > 2:
139 print("Too many arguments.", file=sys.stderr)
140 exit(1)
141 if len(args) > 1:
142 output_file = args[1]
143 if len(args) > 0:
144 input_file = args[0]
145
146 if not os.path.exists(input_file) or os.path.isdir(input_file):
147 print(f"Input file '{input_file}' does not exist.", file=sys.stderr)
148 exit(1)
149
150 #
151
152 print(f"Collecting textures from {len(texturepaths)} path(s)... ", end="", flush=True)
153 textures = {}
154 for path in texturepaths:
155 collect_files(path)
156 print("done")
157
158 print("Processing nodes...")
159 fin = open(input_file, 'r')
160 fout = open(output_file, 'w')
161 n = 0
162 for line in fin:
163 line = line.rstrip('\r\n')
164 if not line or line[0] == '#':
165 fout.write(line + '\n')
166 continue
167 node, tex = line.split(" ")
168 if not tex or tex == "blank.png":
169 continue
170 elif tex not in textures.keys():
171 print(f"skip {node} texture not found")
172 continue
173 color = average_color(textures[tex])
174 line = f"{node} {color}"
175 #print(f"ok {node}")
176 line = apply_sed(line, REPLACEMENTS)
177 if line:
178 fout.write(line + '\n')
179 n += 1
180 fin.close()
181 fout.close()
182 print(f"Done, {n} entries written.")
+0
-8
util/travis/script.sh less more
0 #!/bin/bash -e
1 mkdir -p travisbuild
2 cd travisbuild
3
4 cmake .. \
5 -DENABLE_LEVELDB=1
6
7 make -j2
4242 oss << "Setting '" << name << "' not found";
4343 throw std::runtime_error(oss.str());
4444 }
45
46 std::string read_setting_default(const std::string &name, std::istream &is,
47 const std::string &def)
48 {
49 try {
50 return read_setting(name, is);
51 } catch(const std::runtime_error &e) {
52 return def;
53 }
54 }