Compare commits

...

5 Commits

Author SHA1 Message Date
sfan5 7fb3b9edd6 Fix Postgres linking on older CMake
(see 998e4820c9)
2022-06-19 14:14:09 +02:00
sfan5 18f0615002 Fix --drawplayers 2022-02-21 18:42:54 +01:00
sfan5 d75266eae1 Update colors.txt
with all nodes as of Minetest Game 5.5.0
2022-02-21 18:08:54 +01:00
sfan5 31b0d09a19 Warn if only unknown nodes seen
suggested by @Calinou
2022-02-09 23:09:32 +01:00
sfan5 e4bf375ac7 General code cleanups/maintenance 2022-02-09 23:09:32 +01:00
19 changed files with 176 additions and 157 deletions

View File

@ -86,6 +86,7 @@ if(ENABLE_POSTGRESQL)
if(PostgreSQL_INCLUDE_DIR AND PostgreSQL_LIBRARY) if(PostgreSQL_INCLUDE_DIR AND PostgreSQL_LIBRARY)
set(PostgreSQL_FOUND TRUE) set(PostgreSQL_FOUND TRUE)
set(PostgreSQL_INCLUDE_DIRS ${PostgreSQL_INCLUDE_DIR}) set(PostgreSQL_INCLUDE_DIRS ${PostgreSQL_INCLUDE_DIR})
set(PostgreSQL_LIBRARIES ${PostgreSQL_LIBRARY})
endif() endif()
else() else()
find_package(PostgreSQL) find_package(PostgreSQL)

View File

@ -26,11 +26,10 @@ static inline int color2int(const Color &c)
static inline Color int2color(int c) static inline Color int2color(int c)
{ {
Color c2; Color c2;
u8 a;
c2.b = c & 0xff; c2.b = c & 0xff;
c2.g = (c >> 8) & 0xff; c2.g = (c >> 8) & 0xff;
c2.r = (c >> 16) & 0xff; c2.r = (c >> 16) & 0xff;
a = (c >> 24) & 0xff; u8 a = (c >> 24) & 0xff;
c2.a = 255 - (a*255 / gdAlphaMax); c2.a = 255 - (a*255 / gdAlphaMax);
return c2; return c2;
} }
@ -55,7 +54,7 @@ static inline void check_bounds(int x, int y, int width, int height)
Image::Image(int width, int height) : Image::Image(int width, int height) :
m_width(width), m_height(height), m_image(NULL) m_width(width), m_height(height), m_image(nullptr)
{ {
SIZECHECK(0, 0); SIZECHECK(0, 0);
m_image = gdImageCreateTrueColor(m_width, m_height); m_image = gdImageCreateTrueColor(m_width, m_height);

View File

@ -22,14 +22,14 @@ PlayerAttributes::PlayerAttributes(const std::string &worldDir)
else if (backend == "sqlite3") else if (backend == "sqlite3")
readSqlite(worldDir + "players.sqlite"); readSqlite(worldDir + "players.sqlite");
else else
throw std::runtime_error(((std::string) "Unknown player backend: ") + backend); throw std::runtime_error(std::string("Unknown player backend: ") + backend);
} }
void PlayerAttributes::readFiles(const std::string &playersPath) void PlayerAttributes::readFiles(const std::string &playersPath)
{ {
DIR *dir; DIR *dir;
dir = opendir (playersPath.c_str()); dir = opendir (playersPath.c_str());
if (dir == NULL) if (!dir)
return; return;
struct dirent *ent; struct dirent *ent;
@ -37,9 +37,8 @@ void PlayerAttributes::readFiles(const std::string &playersPath)
if (ent->d_name[0] == '.') if (ent->d_name[0] == '.')
continue; continue;
std::string path = playersPath + PATH_SEPARATOR + ent->d_name; std::ifstream in(playersPath + PATH_SEPARATOR + ent->d_name);
std::ifstream in(path); if (!in.good())
if(!in.good())
continue; continue;
std::string name, position; std::string name, position;
@ -57,16 +56,17 @@ void PlayerAttributes::readFiles(const std::string &playersPath)
iss >> tmp; // ',' iss >> tmp; // ','
iss >> player.z; iss >> player.z;
iss >> tmp; // ')' iss >> tmp; // ')'
if(tmp != ')') if (tmp != ')')
continue; continue;
player.name = name; player.name = name;
player.x /= 10.0; player.x /= 10.0f;
player.y /= 10.0; player.y /= 10.0f;
player.z /= 10.0; player.z /= 10.0f;
m_players.push_back(player); m_players.push_back(player);
} }
closedir(dir); closedir(dir);
} }
@ -101,14 +101,14 @@ void PlayerAttributes::readSqlite(const std::string &db_name)
Player player; Player player;
const unsigned char *name_ = sqlite3_column_text(stmt_get_player_pos, 0); const unsigned char *name_ = sqlite3_column_text(stmt_get_player_pos, 0);
player.name = std::string(reinterpret_cast<const char*>(name_)); player.name = reinterpret_cast<const char*>(name_);
player.x = sqlite3_column_double(stmt_get_player_pos, 1); player.x = sqlite3_column_double(stmt_get_player_pos, 1);
player.y = sqlite3_column_double(stmt_get_player_pos, 2); player.y = sqlite3_column_double(stmt_get_player_pos, 2);
player.z = sqlite3_column_double(stmt_get_player_pos, 3); player.z = sqlite3_column_double(stmt_get_player_pos, 3);
player.x /= 10.0; player.x /= 10.0f;
player.y /= 10.0; player.y /= 10.0f;
player.z /= 10.0; player.z /= 10.0f;
m_players.push_back(player); m_players.push_back(player);
} }

View File

@ -33,18 +33,6 @@
#define __has_builtin(x) 0 #define __has_builtin(x) 0
#endif #endif
template<typename T>
static inline T mymax(T a, T b)
{
return (a > b) ? a : b;
}
template<typename T>
static inline T mymin(T a, T b)
{
return (a > b) ? b : a;
}
// saturating multiplication // saturating multiplication
template<typename T, class = typename std::enable_if<std::is_unsigned<T>::value>::type> template<typename T, class = typename std::enable_if<std::is_unsigned<T>::value>::type>
inline T sat_mul(T a, T b) inline T sat_mul(T a, T b)
@ -92,7 +80,7 @@ static int round_multiple_nosign(int n, int f)
return sign * (abs_n + f - (abs_n % f)); return sign * (abs_n + f - (abs_n % f));
} }
static inline unsigned int colorSafeBounds (int channel) static inline unsigned int colorSafeBounds(int channel)
{ {
return mymin(mymax(channel, 0), 255); return mymin(mymax(channel, 0), 255);
} }
@ -152,6 +140,7 @@ TileGenerator::TileGenerator():
m_geomX2(2048), m_geomX2(2048),
m_geomY2(2048), m_geomY2(2048),
m_exhaustiveSearch(EXH_AUTO), m_exhaustiveSearch(EXH_AUTO),
m_renderedAny(false),
m_zoom(1), m_zoom(1),
m_scales(SCALE_LEFT | SCALE_TOP), m_scales(SCALE_LEFT | SCALE_TOP),
m_progressMax(0), m_progressMax(0),
@ -267,12 +256,8 @@ void TileGenerator::parseColorsFile(const std::string &fileName)
parseColorsStream(in); parseColorsStream(in);
} }
void TileGenerator::printGeometry(const std::string &input) void TileGenerator::printGeometry(const std::string &input_path)
{ {
std::string input_path = input;
if (input_path.back() != PATH_SEPARATOR)
input_path += PATH_SEPARATOR;
setExhaustiveSearch(EXH_NEVER); setExhaustiveSearch(EXH_NEVER);
openDb(input_path); openDb(input_path);
loadBlocks(); loadBlocks();
@ -284,15 +269,10 @@ void TileGenerator::printGeometry(const std::string &input)
<< std::endl; << std::endl;
closeDatabase(); closeDatabase();
} }
void TileGenerator::dumpBlock(const std::string &input, BlockPos pos) void TileGenerator::dumpBlock(const std::string &input_path, BlockPos pos)
{ {
std::string input_path = input;
if (input_path.back() != PATH_SEPARATOR)
input_path += PATH_SEPARATOR;
openDb(input_path); openDb(input_path);
BlockList list; BlockList list;
@ -309,12 +289,8 @@ void TileGenerator::dumpBlock(const std::string &input, BlockPos pos)
closeDatabase(); closeDatabase();
} }
void TileGenerator::generate(const std::string &input, const std::string &output) void TileGenerator::generate(const std::string &input_path, const std::string &output)
{ {
std::string input_path = input;
if (input_path.back() != PATH_SEPARATOR)
input_path += PATH_SEPARATOR;
if (m_dontWriteEmpty) // FIXME: possible too, just needs to be done differently if (m_dontWriteEmpty) // FIXME: possible too, just needs to be done differently
setExhaustiveSearch(EXH_NEVER); setExhaustiveSearch(EXH_NEVER);
openDb(input_path); openDb(input_path);
@ -348,21 +324,19 @@ void TileGenerator::parseColorsStream(std::istream &in)
while (in.good()) { while (in.good()) {
in.getline(line, sizeof(line)); in.getline(line, sizeof(line));
for(char *p = line; *p; p++) { for (char *p = line; *p; p++) {
if(*p != '#') if (*p != '#')
continue; continue;
*p = '\0'; // Cut off at the first # *p = '\0'; // Cut off at the first #
break; break;
} }
if(strlen(line) == 0) if(!line[0])
continue; continue;
char name[128 + 1] = {0}; char name[200 + 1] = {0};
unsigned int r, g, b, a, t; unsigned int r, g, b, a = 255, t = 0;
a = 255; int items = sscanf(line, "%200s %u %u %u %u %u", name, &r, &g, &b, &a, &t);
t = 0; if (items < 4) {
int items = sscanf(line, "%128s %u %u %u %u %u", name, &r, &g, &b, &a, &t);
if(items < 4) {
std::cerr << "Failed to parse color entry '" << line << "'" << std::endl; std::cerr << "Failed to parse color entry '" << line << "'" << std::endl;
continue; continue;
} }
@ -387,33 +361,37 @@ std::set<std::string> TileGenerator::getSupportedBackends()
return r; return r;
} }
void TileGenerator::openDb(const std::string &input) void TileGenerator::openDb(const std::string &input_path)
{ {
std::string input = input_path;
if (input.back() != PATH_SEPARATOR)
input += PATH_SEPARATOR;
std::string backend = m_backend; std::string backend = m_backend;
if (backend == "") { if (backend.empty()) {
std::ifstream ifs(input + "/world.mt"); std::ifstream ifs(input + "world.mt");
if(!ifs.good()) if(!ifs.good())
throw std::runtime_error("Failed to open world.mt"); throw std::runtime_error("Failed to open world.mt");
backend = read_setting_default("backend", ifs, "sqlite3"); backend = read_setting_default("backend", ifs, "sqlite3");
ifs.close(); ifs.close();
} }
if(backend == "sqlite3") if (backend == "sqlite3")
m_db = new DBSQLite3(input); m_db = new DBSQLite3(input);
#if USE_POSTGRESQL #if USE_POSTGRESQL
else if(backend == "postgresql") else if (backend == "postgresql")
m_db = new DBPostgreSQL(input); m_db = new DBPostgreSQL(input);
#endif #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);
#endif #endif
#if USE_REDIS #if USE_REDIS
else if(backend == "redis") else if (backend == "redis")
m_db = new DBRedis(input); m_db = new DBRedis(input);
#endif #endif
else else
throw std::runtime_error(((std::string) "Unknown map backend: ") + backend); throw std::runtime_error(std::string("Unknown map backend: ") + backend);
// Determine how we're going to traverse the database (heuristic) // Determine how we're going to traverse the database (heuristic)
if (m_exhaustiveSearch == EXH_AUTO) { if (m_exhaustiveSearch == EXH_AUTO) {
@ -494,7 +472,6 @@ void TileGenerator::createImage()
if(!m_drawScale) if(!m_drawScale)
m_scales = 0; m_scales = 0;
// If a geometry is explicitly set, set the bounding box to the requested geometry // If a geometry is explicitly set, set the bounding box to the requested geometry
// instead of cropping to the content. This way we will always output a full tile // instead of cropping to the content. This way we will always output a full tile
// of the correct size. // of the correct size.
@ -566,6 +543,7 @@ void TileGenerator::renderMap()
} }
if (!m_readPixels.full()) if (!m_readPixels.full())
renderMapBlockBottom(blockStack.begin()->first); renderMapBlockBottom(blockStack.begin()->first);
m_renderedAny |= m_readInfo.any();
}; };
auto postRenderRow = [&] (int16_t zPos) { auto postRenderRow = [&] (int16_t zPos) {
if (m_shading) if (m_shading)
@ -839,9 +817,13 @@ void TileGenerator::renderOrigin()
m_image->drawCircle(getImageX(0, true), getImageY(0, true), 12, m_originColor); m_image->drawCircle(getImageX(0, true), getImageY(0, true), 12, m_originColor);
} }
void TileGenerator::renderPlayers(const std::string &inputPath) void TileGenerator::renderPlayers(const std::string &input_path)
{ {
PlayerAttributes players(inputPath); std::string input = input_path;
if (input.back() != PATH_SEPARATOR)
input += PATH_SEPARATOR;
PlayerAttributes players(input);
for (auto &player : players) { for (auto &player : players) {
if (player.x < m_xMin * 16 || player.x > m_xMax * 16 || if (player.x < m_xMin * 16 || player.x > m_xMax * 16 ||
player.z < m_zMin * 16 || player.z > m_zMax * 16) player.z < m_zMin * 16 || player.z > m_zMax * 16)
@ -861,16 +843,21 @@ void TileGenerator::writeImage(const std::string &output)
{ {
m_image->save(output); m_image->save(output);
delete m_image; delete m_image;
m_image = NULL; m_image = nullptr;
} }
void TileGenerator::printUnknown() void TileGenerator::printUnknown()
{ {
if (m_unknownNodes.size() == 0) if (m_unknownNodes.empty())
return; return;
std::cerr << "Unknown nodes:" << std::endl; std::cerr << "Unknown nodes:" << std::endl;
for (const auto &node : m_unknownNodes) for (const auto &node : m_unknownNodes)
std::cerr << "\t" << node << std::endl; std::cerr << "\t" << node << std::endl;
if (!m_renderedAny) {
std::cerr << "The map was read successfully and not empty, but none of the "
"encountered nodes had a color associated.\nCheck that you're using "
"the right colors.txt. It should match the game you have installed." << std::endl;
}
} }
void TileGenerator::reportProgress(size_t count) void TileGenerator::reportProgress(size_t count)

View File

@ -2,7 +2,7 @@
#include <stdint.h> #include <stdint.h>
#include "ZlibDecompressor.h" #include "ZlibDecompressor.h"
ZlibDecompressor::ZlibDecompressor(const unsigned char *data, std::size_t size): ZlibDecompressor::ZlibDecompressor(const u8 *data, size_t size):
m_data(data), m_data(data),
m_seekPos(0), m_seekPos(0),
m_size(size) m_size(size)
@ -13,12 +13,12 @@ ZlibDecompressor::~ZlibDecompressor()
{ {
} }
void ZlibDecompressor::setSeekPos(std::size_t seekPos) void ZlibDecompressor::setSeekPos(size_t seekPos)
{ {
m_seekPos = seekPos; m_seekPos = seekPos;
} }
std::size_t ZlibDecompressor::seekPos() const size_t ZlibDecompressor::seekPos() const
{ {
return m_seekPos; return m_seekPos;
} }
@ -26,7 +26,7 @@ std::size_t ZlibDecompressor::seekPos() const
ustring ZlibDecompressor::decompress() ustring ZlibDecompressor::decompress()
{ {
const unsigned char *data = m_data + m_seekPos; const unsigned char *data = m_data + m_seekPos;
const std::size_t size = m_size - m_seekPos; const size_t size = m_size - m_seekPos;
ustring buffer; ustring buffer;
constexpr size_t BUFSIZE = 128 * 1024; constexpr size_t BUFSIZE = 128 * 1024;
@ -54,7 +54,7 @@ ustring ZlibDecompressor::decompress()
throw DecompressError(); throw DecompressError();
m_seekPos += strm.next_in - data; m_seekPos += strm.next_in - data;
(void)inflateEnd(&strm); (void) inflateEnd(&strm);
return buffer; return buffer;
} }

View File

@ -10,7 +10,7 @@ bones:bones 117 117 117
# butterflies # butterflies
# carts # carts
carts:brakerail 138 121 102 carts:brakerail 150 121 102
carts:powerrail 160 145 102 carts:powerrail 160 145 102
carts:rail 146 128 108 carts:rail 146 128 108
@ -117,7 +117,11 @@ default:marram_grass_1 113 139 96
default:marram_grass_2 102 131 90 default:marram_grass_2 102 131 90
default:marram_grass_3 99 130 88 default:marram_grass_3 99 130 88
default:mese 222 222 0 default:mese 222 222 0
default:mese_post_light 134 105 59 default:mese_post_light 132 103 57
default:mese_post_light_acacia_wood 151 62 39
default:mese_post_light_aspen_wood 210 199 170
default:mese_post_light_junglewood 57 39 14
default:mese_post_light_pine_wood 221 185 131
default:meselamp 213 215 143 default:meselamp 213 215 143
default:mossycobble 88 91 73 default:mossycobble 88 91 73
default:obsidian 21 24 29 default:obsidian 21 24 29
@ -174,12 +178,20 @@ default:wood 131 102 57
# doors # doors
doors:door_glass_a 245 245 245 64 16 doors:door_glass_a 245 245 245 64 16
doors:door_glass_b 245 245 245 64 16 doors:door_glass_b 245 245 245 64 16
doors:door_glass_c 245 245 245 64 16
doors:door_glass_d 245 245 245 64 16
doors:door_obsidian_glass_a 48 49 50 64 16 doors:door_obsidian_glass_a 48 49 50 64 16
doors:door_obsidian_glass_b 48 49 50 64 16 doors:door_obsidian_glass_b 48 49 50 64 16
doors:door_obsidian_glass_c 48 49 50 64 16
doors:door_obsidian_glass_d 48 49 50 64 16
doors:door_steel_a 203 203 203 doors:door_steel_a 203 203 203
doors:door_steel_b 203 203 203 doors:door_steel_b 203 203 203
doors:door_steel_c 203 203 203
doors:door_steel_d 203 203 203
doors:door_wood_a 89 68 37 doors:door_wood_a 89 68 37
doors:door_wood_b 89 68 37 doors:door_wood_b 89 68 37
doors:door_wood_c 89 68 37
doors:door_wood_d 89 68 37
doors:gate_acacia_wood_closed 150 61 39 doors:gate_acacia_wood_closed 150 61 39
doors:gate_acacia_wood_open 150 61 39 doors:gate_acacia_wood_open 150 61 39
doors:gate_aspen_wood_closed 210 199 170 doors:gate_aspen_wood_closed 210 199 170
@ -204,6 +216,7 @@ farming:cotton_5 116 105 53
farming:cotton_6 121 95 59 farming:cotton_6 121 95 59
farming:cotton_7 94 70 37 farming:cotton_7 94 70 37
farming:cotton_8 122 108 93 farming:cotton_8 122 108 93
farming:cotton_wild 111 111 101
farming:desert_sand_soil 161 132 72 farming:desert_sand_soil 161 132 72
farming:desert_sand_soil_wet 120 99 53 farming:desert_sand_soil_wet 120 99 53
farming:dry_soil 178 136 90 farming:dry_soil 178 136 90
@ -432,6 +445,8 @@ xpanes:bar 114 114 114 64 16
xpanes:bar_flat 114 114 114 64 16 xpanes:bar_flat 114 114 114 64 16
xpanes:door_steel_bar_a 133 133 133 64 16 xpanes:door_steel_bar_a 133 133 133 64 16
xpanes:door_steel_bar_b 133 133 133 64 16 xpanes:door_steel_bar_b 133 133 133 64 16
xpanes:door_steel_bar_c 133 133 133 64 16
xpanes:door_steel_bar_d 133 133 133 64 16
xpanes:obsidian_pane 16 17 18 64 16 xpanes:obsidian_pane 16 17 18 64 16
xpanes:obsidian_pane_flat 16 17 18 64 16 xpanes:obsidian_pane_flat 16 17 18 64 16
xpanes:pane 249 249 249 64 16 xpanes:pane 249 249 249 64 16

View File

@ -5,7 +5,7 @@
static inline int64_t stoi64(const std::string &s) static inline int64_t stoi64(const std::string &s)
{ {
std::stringstream tmp(s); std::istringstream tmp(s);
int64_t t; int64_t t;
tmp >> t; tmp >> t;
return t; return t;

View File

@ -11,8 +11,8 @@
DBPostgreSQL::DBPostgreSQL(const std::string &mapdir) DBPostgreSQL::DBPostgreSQL(const std::string &mapdir)
{ {
std::ifstream ifs((mapdir + "/world.mt").c_str()); std::ifstream ifs(mapdir + "world.mt");
if(!ifs.good()) if (!ifs.good())
throw std::runtime_error("Failed to read world.mt"); throw std::runtime_error("Failed to read world.mt");
std::string connect_string = read_setting("pgsql_connection", ifs); std::string connect_string = read_setting("pgsql_connection", ifs);
ifs.close(); ifs.close();

View File

@ -20,7 +20,6 @@ static inline int64_t stoi64(const std::string &s)
return t; return t;
} }
static inline std::string i64tos(int64_t i) static inline std::string i64tos(int64_t i)
{ {
std::ostringstream os; std::ostringstream os;
@ -28,10 +27,11 @@ static inline std::string i64tos(int64_t i)
return os.str(); return os.str();
} }
DBRedis::DBRedis(const std::string &mapdir) DBRedis::DBRedis(const std::string &mapdir)
{ {
std::ifstream ifs((mapdir + "/world.mt").c_str()); std::ifstream ifs(mapdir + "world.mt");
if(!ifs.good()) if (!ifs.good())
throw std::runtime_error("Failed to read world.mt"); throw std::runtime_error("Failed to read world.mt");
std::string tmp; std::string tmp;
@ -40,12 +40,16 @@ DBRedis::DBRedis(const std::string &mapdir)
hash = read_setting("redis_hash", ifs); hash = read_setting("redis_hash", ifs);
ifs.seekg(0); ifs.seekg(0);
const char *addr = tmp.c_str(); if (tmp.find('/') != std::string::npos) {
int port = stoi64(read_setting_default("redis_port", ifs, "6379")); ctx = redisConnectUnix(tmp.c_str());
ctx = tmp.find('/') != std::string::npos ? redisConnectUnix(addr) : redisConnect(addr, port); } else {
if(!ctx) { int port = stoi64(read_setting_default("redis_port", ifs, "6379"));
ctx = redisConnect(tmp.c_str(), port);
}
if (!ctx) {
throw std::runtime_error("Cannot allocate redis context"); throw std::runtime_error("Cannot allocate redis context");
} else if(ctx->err) { } else if (ctx->err) {
std::string err = std::string("Connection error: ") + ctx->errstr; std::string err = std::string("Connection error: ") + ctx->errstr;
redisFree(ctx); redisFree(ctx);
throw std::runtime_error(err); throw std::runtime_error(err);
@ -82,8 +86,9 @@ std::vector<BlockPos> DBRedis::getBlockPos(BlockPos min, BlockPos max)
} }
const char *DBRedis::replyTypeStr(int type) { const char *DBRedis::replyTypeStr(int type)
switch(type) { {
switch (type) {
case REDIS_REPLY_STATUS: case REDIS_REPLY_STATUS:
return "REDIS_REPLY_STATUS"; return "REDIS_REPLY_STATUS";
case REDIS_REPLY_ERROR: case REDIS_REPLY_ERROR:
@ -97,7 +102,7 @@ const char *DBRedis::replyTypeStr(int type) {
case REDIS_REPLY_ARRAY: case REDIS_REPLY_ARRAY:
return "REDIS_REPLY_ARRAY"; return "REDIS_REPLY_ARRAY";
default: default:
return "unknown"; return "(unknown)";
} }
} }
@ -106,12 +111,12 @@ void DBRedis::loadPosCache()
{ {
redisReply *reply; redisReply *reply;
reply = (redisReply*) redisCommand(ctx, "HKEYS %s", hash.c_str()); reply = (redisReply*) redisCommand(ctx, "HKEYS %s", hash.c_str());
if(!reply) if (!reply)
throw std::runtime_error("Redis command HKEYS failed"); throw std::runtime_error("Redis command HKEYS failed");
if(reply->type != REDIS_REPLY_ARRAY) if (reply->type != REDIS_REPLY_ARRAY)
REPLY_TYPE_ERR(reply, "HKEYS reply"); REPLY_TYPE_ERR(reply, "HKEYS reply");
for(size_t i = 0; i < reply->elements; i++) { for (size_t i = 0; i < reply->elements; i++) {
if(reply->element[i]->type != REDIS_REPLY_STRING) if (reply->element[i]->type != REDIS_REPLY_STRING)
REPLY_TYPE_ERR(reply->element[i], "HKEYS subreply"); REPLY_TYPE_ERR(reply->element[i], "HKEYS subreply");
BlockPos pos = decodeBlockPos(stoi64(reply->element[i]->str)); BlockPos pos = decodeBlockPos(stoi64(reply->element[i]->str));
posCache[pos.z].emplace_back(pos.x, pos.y); posCache[pos.z].emplace_back(pos.x, pos.y);
@ -128,25 +133,24 @@ void DBRedis::HMGET(const std::vector<BlockPos> &positions,
argv[0] = "HMGET"; argv[0] = "HMGET";
argv[1] = hash.c_str(); argv[1] = hash.c_str();
std::vector<BlockPos>::const_iterator position = positions.begin(); auto position = positions.begin();
std::size_t remaining = positions.size(); size_t remaining = positions.size();
std::size_t abs_i = 0; size_t abs_i = 0;
while (remaining > 0) { while (remaining > 0) {
const std::size_t batch_size = const size_t batch_size = mymin<size_t>(DB_REDIS_HMGET_NUMFIELDS, remaining);
(remaining > DB_REDIS_HMGET_NUMFIELDS) ? DB_REDIS_HMGET_NUMFIELDS : remaining;
redisReply *reply; redisReply *reply;
{ {
// storage to preserve validity of .c_str() // storage to preserve validity of .c_str()
std::string keys[batch_size]; std::string keys[batch_size];
for (std::size_t i = 0; i < batch_size; ++i) { for (size_t i = 0; i < batch_size; ++i) {
keys[i] = i64tos(encodeBlockPos(*position++)); keys[i] = i64tos(encodeBlockPos(*position++));
argv[i+2] = keys[i].c_str(); argv[i+2] = keys[i].c_str();
} }
reply = (redisReply*) redisCommandArgv(ctx, batch_size + 2, argv, NULL); reply = (redisReply*) redisCommandArgv(ctx, batch_size + 2, argv, NULL);
} }
if(!reply) if (!reply)
throw std::runtime_error("Redis command HMGET failed"); throw std::runtime_error("Redis command HMGET failed");
if (reply->type != REDIS_REPLY_ARRAY) if (reply->type != REDIS_REPLY_ARRAY)
REPLY_TYPE_ERR(reply, "HMGET reply"); REPLY_TYPE_ERR(reply, "HMGET reply");
@ -154,7 +158,7 @@ void DBRedis::HMGET(const std::vector<BlockPos> &positions,
freeReplyObject(reply); freeReplyObject(reply);
throw std::runtime_error("HMGET wrong number of elements"); throw std::runtime_error("HMGET wrong number of elements");
} }
for (std::size_t i = 0; i < reply->elements; ++i) { for (size_t i = 0; i < reply->elements; ++i) {
redisReply *subreply = reply->element[i]; redisReply *subreply = reply->element[i];
if (subreply->type == REDIS_REPLY_NIL) if (subreply->type == REDIS_REPLY_NIL)
continue; continue;
@ -162,10 +166,14 @@ void DBRedis::HMGET(const std::vector<BlockPos> &positions,
REPLY_TYPE_ERR(subreply, "HMGET subreply"); REPLY_TYPE_ERR(subreply, "HMGET subreply");
if (subreply->len == 0) if (subreply->len == 0)
throw std::runtime_error("HMGET empty string"); throw std::runtime_error("HMGET empty string");
result(abs_i + i, ustring((const unsigned char *) subreply->str, subreply->len)); result(abs_i + i, ustring(
reinterpret_cast<const unsigned char*>(subreply->str),
subreply->len
));
} }
freeReplyObject(reply); freeReplyObject(reply);
abs_i += reply->elements;
abs_i += batch_size;
remaining -= batch_size; remaining -= batch_size;
} }
} }

View File

@ -151,7 +151,7 @@ void DBSQLite3::getBlocksOnXZ(BlockList &blocks, int16_t x, int16_t z,
* because it's bad for performance. But rather than silently breaking * because it's bad for performance. But rather than silently breaking
* do the right thing and load the blocks again. */ * do the right thing and load the blocks again. */
#ifndef NDEBUG #ifndef NDEBUG
std::cout << "Warning: suboptimal access pattern for sqlite3 backend" << std::endl; std::cerr << "Warning: suboptimal access pattern for sqlite3 backend" << std::endl;
#endif #endif
loadBlockCache(z); loadBlockCache(z);
} }

View File

@ -2,13 +2,16 @@
#include <climits> #include <climits>
#include <cstdint> #include <cstdint>
#include "config.h"
#define BLOCK_SIZE 16
struct PixelAttribute { struct PixelAttribute {
PixelAttribute(): height(INT16_MIN), thickness(0) {}; PixelAttribute() : height(INT16_MIN), thickness(0) {};
int16_t height; int16_t height;
uint8_t thickness; uint8_t thickness;
inline bool valid_height() {
inline bool valid_height() const {
return height != INT16_MIN; return height != INT16_MIN;
} }
}; };
@ -18,8 +21,10 @@ class PixelAttributes
public: public:
PixelAttributes(); PixelAttributes();
virtual ~PixelAttributes(); virtual ~PixelAttributes();
void setWidth(int width); void setWidth(int width);
void scroll(); void scroll();
inline PixelAttribute &attribute(int z, int x) { inline PixelAttribute &attribute(int z, int x) {
return m_pixelAttributes[z + 1][x + 1]; return m_pixelAttributes[z + 1][x + 1];
}; };

View File

@ -6,7 +6,7 @@
struct Player struct Player
{ {
std::string name; std::string name;
double x, y, z; float x, y, z;
}; };
class PlayerAttributes class PlayerAttributes

View File

@ -4,7 +4,6 @@
#include <map> #include <map>
#include <set> #include <set>
#include <unordered_map> #include <unordered_map>
#include <unordered_set>
#include <cstdint> #include <cstdint>
#include <string> #include <string>
@ -44,17 +43,19 @@ struct BitmapThing { // 16x16 bitmap
for (int i = 0; i < 16; ++i) for (int i = 0; i < 16; ++i)
val[i] = 0; val[i] = 0;
} }
inline bool full() const { inline bool any_neq(uint16_t v) const {
for (int i = 0; i < 16; ++i) { for (int i = 0; i < 16; ++i) {
if (val[i] != 0xffff) if (val[i] != v)
return false; return true;
} }
return true; return false;
} }
inline bool any() const { return any_neq(0); }
inline bool full() const { return !any_neq(0xffff); }
inline void set(unsigned int x, unsigned int z) { inline void set(unsigned int x, unsigned int z) {
val[z] |= (1 << x); val[z] |= (1 << x);
} }
inline bool get(unsigned int x, unsigned int z) { inline bool get(unsigned int x, unsigned int z) const {
return !!(val[z] & (1 << x)); return !!(val[z] & (1 << x));
} }
@ -66,7 +67,6 @@ class TileGenerator
{ {
private: private:
typedef std::unordered_map<std::string, ColorEntry> ColorMap; typedef std::unordered_map<std::string, ColorEntry> ColorMap;
typedef std::unordered_set<std::string> NameSet;
public: public:
TileGenerator(); TileGenerator();
@ -150,11 +150,12 @@ private:
int m_mapWidth; int m_mapWidth;
int m_mapHeight; int m_mapHeight;
int m_exhaustiveSearch; int m_exhaustiveSearch;
std::set<std::string> m_unknownNodes;
bool m_renderedAny;
std::map<int16_t, std::set<int16_t>> m_positions; /* indexed by Z, contains X coords */ std::map<int16_t, std::set<int16_t>> m_positions; /* indexed by Z, contains X coords */
ColorMap m_colorMap; ColorMap m_colorMap;
BitmapThing m_readPixels; BitmapThing m_readPixels;
BitmapThing m_readInfo; BitmapThing m_readInfo;
NameSet m_unknownNodes;
Color m_color[16][16]; Color m_color[16][16];
uint8_t m_thickness[16][16]; uint8_t m_thickness[16][16];

View File

@ -16,6 +16,5 @@ public:
private: private:
const u8 *m_data; const u8 *m_data;
size_t m_seekPos; size_t m_seekPos, m_size;
size_t m_size;
}; };

View File

@ -4,8 +4,6 @@
#define PATH_SEPARATOR '/' #define PATH_SEPARATOR '/'
#endif #endif
#define BLOCK_SIZE 16
#ifdef USE_CMAKE_CONFIG_H #ifdef USE_CMAKE_CONFIG_H
#include "cmake_config.h" #include "cmake_config.h"
#else #else

View File

@ -21,7 +21,7 @@ protected:
PGresult *execPrepared( PGresult *execPrepared(
const char *stmtName, const int paramsNumber, const char *stmtName, const int paramsNumber,
const void **params, const void **params,
const int *paramsLengths = NULL, const int *paramsFormats = NULL, const int *paramsLengths = nullptr, const int *paramsFormats = nullptr,
bool clear = true bool clear = true
); );
int pg_binary_to_int(PGresult *res, int row, int col); int pg_binary_to_int(PGresult *res, int row, int col);

View File

@ -1,7 +1,19 @@
#pragma once #pragma once
#include <string> #include <string>
#include <fstream> #include <iostream>
template<typename T>
static inline T mymax(T a, T b)
{
return (a > b) ? a : b;
}
template<typename T>
static inline T mymin(T a, T b)
{
return (a > b) ? b : a;
}
std::string read_setting(const std::string &name, std::istream &is); std::string read_setting(const std::string &name, std::istream &is);

View File

@ -57,28 +57,36 @@ static void usage()
printf("\n"); printf("\n");
} }
static bool file_exists(const std::string &path) static inline bool file_exists(const std::string &path)
{ {
std::ifstream ifs(path); std::ifstream ifs(path);
return ifs.is_open(); return ifs.is_open();
} }
static inline int stoi(const char *s)
{
std::istringstream iss(s);
int ret;
iss >> ret;
return ret;
}
static std::string search_colors(const std::string &worldpath) static std::string search_colors(const std::string &worldpath)
{ {
if(file_exists(worldpath + "/colors.txt")) if (file_exists(worldpath + "/colors.txt"))
return worldpath + "/colors.txt"; return worldpath + "/colors.txt";
#ifndef _WIN32 #ifndef _WIN32
char *home = std::getenv("HOME"); char *home = std::getenv("HOME");
if(home) { if (home) {
std::string check = ((std::string) home) + "/.minetest/colors.txt"; std::string check = std::string(home) + "/.minetest/colors.txt";
if(file_exists(check)) if (file_exists(check))
return check; return check;
} }
#endif #endif
constexpr bool sharedir_valid = !(SHAREDIR[0] == '.' || SHAREDIR[0] == '\0'); constexpr bool sharedir_valid = !(SHAREDIR[0] == '.' || SHAREDIR[0] == '\0');
if(sharedir_valid && file_exists(SHAREDIR "/colors.txt")) if (sharedir_valid && file_exists(SHAREDIR "/colors.txt"))
return SHAREDIR "/colors.txt"; return SHAREDIR "/colors.txt";
std::cerr << "Warning: Falling back to using colors.txt from current directory." << std::endl; std::cerr << "Warning: Falling back to using colors.txt from current directory." << std::endl;
@ -171,19 +179,11 @@ int main(int argc, char *argv[])
case 'd': case 'd':
generator.setBackend(optarg); generator.setBackend(optarg);
break; break;
case 'a': { case 'a':
std::istringstream iss(optarg); generator.setMinY(stoi(optarg));
int miny;
iss >> miny;
generator.setMinY(miny);
}
break; break;
case 'c': { case 'c':
std::istringstream iss(optarg); generator.setMaxY(stoi(optarg));
int maxy;
iss >> maxy;
generator.setMaxY(maxy);
}
break; break;
case 'g': { case 'g': {
std::istringstream geometry(optarg); std::istringstream geometry(optarg);
@ -199,23 +199,19 @@ int main(int argc, char *argv[])
break; break;
case 'f': { case 'f': {
uint flags = 0; uint flags = 0;
if(strchr(optarg, 't') != NULL) if (strchr(optarg, 't'))
flags |= SCALE_TOP; flags |= SCALE_TOP;
if(strchr(optarg, 'b') != NULL) if (strchr(optarg, 'b'))
flags |= SCALE_BOTTOM; flags |= SCALE_BOTTOM;
if(strchr(optarg, 'l') != NULL) if (strchr(optarg, 'l'))
flags |= SCALE_LEFT; flags |= SCALE_LEFT;
if(strchr(optarg, 'r') != NULL) if (strchr(optarg, 'r'))
flags |= SCALE_RIGHT; flags |= SCALE_RIGHT;
generator.setScales(flags); generator.setScales(flags);
} }
break; break;
case 'z': { case 'z':
std::istringstream iss(optarg); generator.setZoom(stoi(optarg));
int zoom;
iss >> zoom;
generator.setZoom(zoom);
}
break; break;
case 'C': case 'C':
colors = optarg; colors = optarg;
@ -224,15 +220,13 @@ int main(int argc, char *argv[])
generator.setDontWriteEmpty(true); generator.setDontWriteEmpty(true);
break; break;
case 'j': { case 'j': {
int mode; int mode = EXH_AUTO;;
if (!strcmp(optarg, "never")) if (!strcmp(optarg, "never"))
mode = EXH_NEVER; mode = EXH_NEVER;
else if (!strcmp(optarg, "y")) else if (!strcmp(optarg, "y"))
mode = EXH_Y; mode = EXH_Y;
else if (!strcmp(optarg, "full")) else if (!strcmp(optarg, "full"))
mode = EXH_FULL; mode = EXH_FULL;
else
mode = EXH_AUTO;
generator.setExhaustiveSearch(mode); generator.setExhaustiveSearch(mode);
} }
break; break;
@ -267,7 +261,7 @@ int main(int argc, char *argv[])
return 0; return 0;
} }
if(colors == "") if(colors.empty())
colors = search_colors(input); colors = search_colors(input);
generator.parseColorsFile(colors); generator.parseColorsFile(colors);
generator.generate(input, output); generator.generate(input, output);

View File

@ -3,15 +3,15 @@
#include "util.h" #include "util.h"
static inline std::string trim(const std::string &s) static std::string trim(const std::string &s)
{ {
auto isspace = [] (char c) -> bool { return c == ' ' || c == '\t' || c == '\r' || c == '\n'; }; auto isspace = [] (char c) -> bool { return c == ' ' || c == '\t' || c == '\r' || c == '\n'; };
size_t front = 0; size_t front = 0;
while(isspace(s[front])) while (isspace(s[front]))
++front; ++front;
size_t back = s.size() - 1; size_t back = s.size() - 1;
while(back > front && isspace(s[back])) while (back > front && isspace(s[back]))
--back; --back;
return s.substr(front, back - front + 1); return s.substr(front, back - front + 1);
@ -23,7 +23,7 @@ std::string read_setting(const std::string &name, std::istream &is)
while (is.good()) { while (is.good()) {
is.getline(linebuf, sizeof(linebuf)); is.getline(linebuf, sizeof(linebuf));
for(char *p = linebuf; *p; p++) { for (char *p = linebuf; *p; p++) {
if(*p != '#') if(*p != '#')
continue; continue;
*p = '\0'; // Cut off at the first # *p = '\0'; // Cut off at the first #