diff --git a/src/client.cpp b/src/client.cpp
index a1ae1e6abd6c9402de20c642d84c992a045e4ffd..00b79e92ef181093dc0c52b383d478c31f703e9d 100644
--- a/src/client.cpp
+++ b/src/client.cpp
@@ -47,10 +47,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "config.h"
 #include "version.h"
 #include "drawscene.h"
-#include "subgame.h"
-#include "server.h"
-#include "database.h"
 #include "database-sqlite3.h"
+#include "serialization.h"
 
 extern gui::IGUIEnvironment* guienv;
 
@@ -266,16 +264,13 @@ Client::Client(
 	m_time_of_day_update_timer(0),
 	m_recommended_send_interval(0.1),
 	m_removed_sounds_check_timer(0),
-	m_state(LC_Created)
+	m_state(LC_Created),
+	m_localdb(NULL)
 {
-	/*
-		Add local player
-	*/
-	{
-		Player *player = new LocalPlayer(this, playername);
+	// Add local player
+	m_env.addPlayer(new LocalPlayer(this, playername));
 
-		m_env.addPlayer(player);
-	}
+	m_cache_save_interval = g_settings->getU16("server_map_save_interval");
 
 	m_cache_smooth_lighting = g_settings->getBool("smooth_lighting");
 	m_cache_enable_shaders  = g_settings->getBool("enable_shaders");
@@ -285,10 +280,10 @@ void Client::Stop()
 {
 	//request all client managed threads to stop
 	m_mesh_update_thread.Stop();
-	if (localdb != NULL) {
-		actionstream << "Local map saving ended" << std::endl;
-		localdb->endSave();
-		delete localserver;
+	// Save local server map
+	if (m_localdb) {
+		infostream << "Local map saving ended." << std::endl;
+		m_localdb->endSave();
 	}
 }
 
@@ -679,6 +674,13 @@ void Client::step(float dtime)
 			Send(pkt);
 		}
 	}
+
+	// Write server map
+	if (m_localdb && m_localdb_save_interval.step(dtime,
+			m_cache_save_interval)) {
+		m_localdb->endSave();
+		m_localdb->beginSave();
+	}
 }
 
 bool Client::loadMedia(const std::string &data, const std::string &filename)
@@ -813,34 +815,19 @@ void Client::initLocalMapSaving(const Address &address,
 		const std::string &hostname,
 		bool is_local_server)
 {
-	localdb = NULL;
-
-	if (!g_settings->getBool("enable_local_map_saving") || is_local_server)
+	if (!g_settings->getBool("enable_local_map_saving") || is_local_server) {
 		return;
+	}
 
 	const std::string world_path = porting::path_user
 		+ DIR_DELIM + "worlds"
 		+ DIR_DELIM + "server_"
 		+ hostname + "_" + to_string(address.getPort());
 
-	SubgameSpec gamespec;
-
-	if (!getWorldExists(world_path)) {
-		gamespec = findSubgame(g_settings->get("default_game"));
-		if (!gamespec.isValid())
-			gamespec = findSubgame("minimal");
-	} else {
-		gamespec = findWorldSubgame(world_path);
-	}
-
-	if (!gamespec.isValid()) {
-		errorstream << "Couldn't find subgame for local map saving." << std::endl;
-		return;
-	}
+	fs::CreateAllDirs(world_path);
 
-	localserver = new Server(world_path, gamespec, false, false);
-	localdb = new Database_SQLite3(&(ServerMap&)localserver->getMap(), world_path);
-	localdb->beginSave();
+	m_localdb = new Database_SQLite3(world_path);
+	m_localdb->beginSave();
 	actionstream << "Local map saving started, map will be saved at '" << world_path << "'" << std::endl;
 }
 
@@ -1663,7 +1650,8 @@ void Client::makeScreenshot(IrrlichtDevice *device)
 		if (image) {
 			raw_image->copyTo(image);
 			irr::c8 filename[256];
-			snprintf(filename, sizeof(filename), "%s" DIR_DELIM "screenshot_%u.png",
+			snprintf(filename, sizeof(filename),
+				(std::string("%s") + DIR_DELIM + "screenshot_%u.png").c_str(),
 				 g_settings->get("screenshot_path").c_str(),
 				 device->getTimer()->getRealTime());
 			std::ostringstream sstr;
diff --git a/src/client.h b/src/client.h
index c0146911de8ea7556967c1b5ba3990a1ae599db3..a0add689a8ae443b7311c4efd469e0475524b18c 100644
--- a/src/client.h
+++ b/src/client.h
@@ -48,7 +48,6 @@ struct MapDrawControl;
 class MtEventManager;
 struct PointedThing;
 class Database;
-class Server;
 
 struct QueuedMeshUpdate
 {
@@ -620,8 +619,9 @@ class Client : public con::PeerHandler, public InventoryManager, public IGameDef
 	LocalClientState m_state;
 
 	// Used for saving server map to disk client-side
-	Database *localdb;
-	Server *localserver;
+	Database *m_localdb;
+	IntervalLimiter m_localdb_save_interval;
+	u16 m_cache_save_interval;
 
 	// TODO: Add callback to update these when g_settings changes
 	bool m_cache_smooth_lighting;
diff --git a/src/database-dummy.cpp b/src/database-dummy.cpp
index 5b1a1434121bff436612777dfd3f66652a50ec4d..71f60d81c898188048d8ff5baa0fc935b7ae94e2 100644
--- a/src/database-dummy.cpp
+++ b/src/database-dummy.cpp
@@ -18,64 +18,38 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 */
 
 /*
-Dummy "database" class
+Dummy database class
 */
 
-
 #include "database-dummy.h"
 
-#include "map.h"
-#include "mapsector.h"
-#include "mapblock.h"
-#include "serialization.h"
-#include "main.h"
-#include "settings.h"
-#include "log.h"
-
-Database_Dummy::Database_Dummy(ServerMap *map)
-{
-	srvmap = map;
-}
-
-int Database_Dummy::Initialized(void)
-{
-	return 1;
-}
-
-void Database_Dummy::beginSave() {}
-void Database_Dummy::endSave() {}
 
-bool Database_Dummy::saveBlock(v3s16 blockpos, std::string &data)
+bool Database_Dummy::saveBlock(const v3s16 &pos, const std::string &data)
 {
-	m_database[getBlockAsInteger(blockpos)] = data;
+	m_database[getBlockAsInteger(pos)] = data;
 	return true;
 }
 
-std::string Database_Dummy::loadBlock(v3s16 blockpos)
+std::string Database_Dummy::loadBlock(const v3s16 &pos)
 {
-	if (m_database.count(getBlockAsInteger(blockpos)))
-		return m_database[getBlockAsInteger(blockpos)];
+	s64 i = getBlockAsInteger(pos);
+	if (m_database.count(i))
+		return m_database[i];
 	else
 		return "";
 }
 
-bool Database_Dummy::deleteBlock(v3s16 blockpos)
+bool Database_Dummy::deleteBlock(const v3s16 &pos)
 {
-	m_database.erase(getBlockAsInteger(blockpos));
+	m_database.erase(getBlockAsInteger(pos));
 	return true;
 }
 
 void Database_Dummy::listAllLoadableBlocks(std::vector<v3s16> &dst)
 {
-	for(std::map<u64, std::string>::iterator x = m_database.begin(); x != m_database.end(); ++x)
-	{
-		v3s16 p = getIntegerAsBlock(x->first);
-		//dstream<<"block_i="<<block_i<<" p="<<PP(p)<<std::endl;
-		dst.push_back(p);
+	for (std::map<s64, std::string>::const_iterator x = m_database.begin();
+			x != m_database.end(); ++x) {
+		dst.push_back(getIntegerAsBlock(x->first));
 	}
 }
 
-Database_Dummy::~Database_Dummy()
-{
-	m_database.clear();
-}
diff --git a/src/database-dummy.h b/src/database-dummy.h
index 732a206f8274904c6373ea4e12beee9be3007b93..0cf56928e08d314f2ad11edf5fcc172b106cbc0f 100644
--- a/src/database-dummy.h
+++ b/src/database-dummy.h
@@ -25,22 +25,17 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "database.h"
 #include "irrlichttypes.h"
 
-class ServerMap;
-
 class Database_Dummy : public Database
 {
 public:
-	Database_Dummy(ServerMap *map);
-	virtual void beginSave();
-	virtual void endSave();
-	virtual bool saveBlock(v3s16 blockpos, std::string &data);
-	virtual std::string loadBlock(v3s16 blockpos);
-	virtual bool deleteBlock(v3s16 blockpos);
+	virtual bool saveBlock(const v3s16 &pos, const std::string &data);
+	virtual std::string loadBlock(const v3s16 &pos);
+	virtual bool deleteBlock(const v3s16 &pos);
 	virtual void listAllLoadableBlocks(std::vector<v3s16> &dst);
-	virtual int Initialized(void);
-	~Database_Dummy();
+
 private:
-	ServerMap *srvmap;
-	std::map<u64, std::string> m_database;
+	std::map<s64, std::string> m_database;
 };
+
 #endif
+
diff --git a/src/database-leveldb.cpp b/src/database-leveldb.cpp
index b35e612b6be8b4929fd2a2fed01cca95b7cfb896..e895354a4cac2432617ad2e242982872f1819e12 100644
--- a/src/database-leveldb.cpp
+++ b/src/database-leveldb.cpp
@@ -22,57 +22,54 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #if USE_LEVELDB
 
 #include "database-leveldb.h"
-#include "leveldb/db.h"
 
-#include "map.h"
-#include "mapsector.h"
-#include "mapblock.h"
-#include "serialization.h"
-#include "main.h"
-#include "settings.h"
 #include "log.h"
 #include "filesys.h"
+#include "exceptions.h"
+#include "util/string.h"
+
+#include "leveldb/db.h"
+
 
 #define ENSURE_STATUS_OK(s) \
 	if (!(s).ok()) { \
-		throw FileNotGoodException(std::string("LevelDB error: ") + (s).ToString()); \
+		throw FileNotGoodException(std::string("LevelDB error: ") + \
+				(s).ToString()); \
 	}
 
-Database_LevelDB::Database_LevelDB(ServerMap *map, std::string savedir)
+
+Database_LevelDB::Database_LevelDB(const std::string &savedir)
 {
 	leveldb::Options options;
 	options.create_if_missing = true;
-	leveldb::Status status = leveldb::DB::Open(options, savedir + DIR_DELIM + "map.db", &m_database);
+	leveldb::Status status = leveldb::DB::Open(options,
+		savedir + DIR_DELIM + "map.db", &m_database);
 	ENSURE_STATUS_OK(status);
-	srvmap = map;
 }
 
-int Database_LevelDB::Initialized(void)
+Database_LevelDB::~Database_LevelDB()
 {
-	return 1;
+	delete m_database;
 }
 
-void Database_LevelDB::beginSave() {}
-void Database_LevelDB::endSave() {}
-
-bool Database_LevelDB::saveBlock(v3s16 blockpos, std::string &data)
+bool Database_LevelDB::saveBlock(const v3s16 &pos, const std::string &data)
 {
 	leveldb::Status status = m_database->Put(leveldb::WriteOptions(),
-			i64tos(getBlockAsInteger(blockpos)), data);
+			i64tos(getBlockAsInteger(pos)), data);
 	if (!status.ok()) {
 		errorstream << "WARNING: saveBlock: LevelDB error saving block "
-			<< PP(blockpos) << ": " << status.ToString() << std::endl;
+			<< PP(pos) << ": " << status.ToString() << std::endl;
 		return false;
 	}
 
 	return true;
 }
 
-std::string Database_LevelDB::loadBlock(v3s16 blockpos)
+std::string Database_LevelDB::loadBlock(const v3s16 &pos)
 {
 	std::string datastr;
 	leveldb::Status status = m_database->Get(leveldb::ReadOptions(),
-		i64tos(getBlockAsInteger(blockpos)), &datastr);
+		i64tos(getBlockAsInteger(pos)), &datastr);
 
 	if(status.ok())
 		return datastr;
@@ -80,13 +77,13 @@ std::string Database_LevelDB::loadBlock(v3s16 blockpos)
 		return "";
 }
 
-bool Database_LevelDB::deleteBlock(v3s16 blockpos)
+bool Database_LevelDB::deleteBlock(const v3s16 &pos)
 {
 	leveldb::Status status = m_database->Delete(leveldb::WriteOptions(),
-			i64tos(getBlockAsInteger(blockpos)));
+			i64tos(getBlockAsInteger(pos)));
 	if (!status.ok()) {
 		errorstream << "WARNING: deleteBlock: LevelDB error deleting block "
-			<< PP(blockpos) << ": " << status.ToString() << std::endl;
+			<< PP(pos) << ": " << status.ToString() << std::endl;
 		return false;
 	}
 
@@ -103,8 +100,5 @@ void Database_LevelDB::listAllLoadableBlocks(std::vector<v3s16> &dst)
 	delete it;
 }
 
-Database_LevelDB::~Database_LevelDB()
-{
-	delete m_database;
-}
-#endif
+#endif // USE_LEVELDB
+
diff --git a/src/database-leveldb.h b/src/database-leveldb.h
index 5d44ba3e7a2ed8e2b679dbf20f82b60946f14fd0..4afe2fdc727bc3261803a2b971a788c63b18bcc5 100644
--- a/src/database-leveldb.h
+++ b/src/database-leveldb.h
@@ -28,23 +28,22 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "leveldb/db.h"
 #include <string>
 
-class ServerMap;
-
 class Database_LevelDB : public Database
 {
 public:
-	Database_LevelDB(ServerMap *map, std::string savedir);
-	virtual void beginSave();
-	virtual void endSave();
-	virtual bool saveBlock(v3s16 blockpos, std::string &data);
-	virtual std::string loadBlock(v3s16 blockpos);
-	virtual bool deleteBlock(v3s16 blockpos);
-	virtual void listAllLoadableBlocks(std::vector<v3s16> &dst);
-	virtual int Initialized(void);
+	Database_LevelDB(const std::string &savedir);
 	~Database_LevelDB();
+
+	virtual bool saveBlock(const v3s16 &pos, const std::string &data);
+	virtual std::string loadBlock(const v3s16 &pos);
+	virtual bool deleteBlock(const v3s16 &pos);
+	virtual void listAllLoadableBlocks(std::vector<v3s16> &dst);
+
 private:
-	ServerMap *srvmap;
-	leveldb::DB* m_database;
+	leveldb::DB *m_database;
 };
+
+#endif // USE_LEVELDB
+
 #endif
-#endif
+
diff --git a/src/database-redis.cpp b/src/database-redis.cpp
index 0962e97baa23553ad78de88da3c63673171fc433..7b42274b97394c9ee038194f65582ae7e88f36ca 100644
--- a/src/database-redis.cpp
+++ b/src/database-redis.cpp
@@ -20,84 +20,78 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "config.h"
 
 #if USE_REDIS
-/*
-	Redis databases
-*/
-
 
 #include "database-redis.h"
-#include <hiredis.h>
 
-#include "map.h"
-#include "mapsector.h"
-#include "mapblock.h"
-#include "serialization.h"
-#include "main.h"
 #include "settings.h"
 #include "log.h"
-#include "filesys.h"
+#include "exceptions.h"
+#include "util/string.h"
+
+#include <hiredis.h>
+#include <cassert>
 
 
-Database_Redis::Database_Redis(ServerMap *map, std::string savedir)
+Database_Redis::Database_Redis(Settings &conf)
 {
-	Settings conf;
-	conf.readConfigFile((std::string(savedir) + DIR_DELIM + "world.mt").c_str());
 	std::string tmp;
 	try {
-	tmp = conf.get("redis_address");
-	hash = conf.get("redis_hash");
-	} catch(SettingNotFoundException e) {
-		throw SettingNotFoundException("Set redis_address and redis_hash in world.mt to use the redis backend");
+		tmp = conf.get("redis_address");
+		hash = conf.get("redis_hash");
+	} catch (SettingNotFoundException) {
+		throw SettingNotFoundException("Set redis_address and "
+			"redis_hash in world.mt to use the redis backend");
 	}
 	const char *addr = tmp.c_str();
 	int port = conf.exists("redis_port") ? conf.getU16("redis_port") : 6379;
 	ctx = redisConnect(addr, port);
-	if(!ctx)
+	if (!ctx) {
 		throw FileNotGoodException("Cannot allocate redis context");
-	else if(ctx->err) {
+	} else if(ctx->err) {
 		std::string err = std::string("Connection error: ") + ctx->errstr;
 		redisFree(ctx);
 		throw FileNotGoodException(err);
 	}
-	srvmap = map;
 }
 
-int Database_Redis::Initialized(void)
+Database_Redis::~Database_Redis()
 {
-	return 1;
+	redisFree(ctx);
 }
 
 void Database_Redis::beginSave() {
-	redisReply *reply;
-	reply = (redisReply*) redisCommand(ctx, "MULTI");
-	if(!reply)
-		throw FileNotGoodException(std::string("redis command 'MULTI' failed: ") + ctx->errstr);
+	redisReply *reply = static_cast<redisReply *>(redisCommand(ctx, "MULTI"));
+	if (!reply) {
+		throw FileNotGoodException(std::string(
+			"Redis command 'MULTI' failed: ") + ctx->errstr);
+	}
 	freeReplyObject(reply);
 }
 
 void Database_Redis::endSave() {
-	redisReply *reply;
-	reply = (redisReply*) redisCommand(ctx, "EXEC");
-	if(!reply)
-		throw FileNotGoodException(std::string("redis command 'EXEC' failed: ") + ctx->errstr);
+	redisReply *reply = static_cast<redisReply *>(redisCommand(ctx, "EXEC"));
+	if (!reply) {
+		throw FileNotGoodException(std::string(
+			"Redis command 'EXEC' failed: ") + ctx->errstr);
+	}
 	freeReplyObject(reply);
 }
 
-bool Database_Redis::saveBlock(v3s16 blockpos, std::string &data)
+bool Database_Redis::saveBlock(const v3s16 &pos, const std::string &data)
 {
-	std::string tmp = i64tos(getBlockAsInteger(blockpos));
+	std::string tmp = i64tos(getBlockAsInteger(pos));
 
-	redisReply *reply = (redisReply *)redisCommand(ctx, "HSET %s %s %b",
-			hash.c_str(), tmp.c_str(), data.c_str(), data.size());
+	redisReply *reply = static_cast<redisReply *>(redisCommand(ctx, "HSET %s %s %b",
+			hash.c_str(), tmp.c_str(), data.c_str(), data.size()));
 	if (!reply) {
 		errorstream << "WARNING: saveBlock: redis command 'HSET' failed on "
-			"block " << PP(blockpos) << ": " << ctx->errstr << std::endl;
+			"block " << PP(pos) << ": " << ctx->errstr << std::endl;
 		freeReplyObject(reply);
 		return false;
 	}
 
 	if (reply->type == REDIS_REPLY_ERROR) {
-		errorstream << "WARNING: saveBlock: saving block " << PP(blockpos)
+		errorstream << "WARNING: saveBlock: saving block " << PP(pos)
 			<< "failed" << std::endl;
 		freeReplyObject(reply);
 		return false;
@@ -107,38 +101,36 @@ bool Database_Redis::saveBlock(v3s16 blockpos, std::string &data)
 	return true;
 }
 
-std::string Database_Redis::loadBlock(v3s16 blockpos)
+std::string Database_Redis::loadBlock(const v3s16 &pos)
 {
-	std::string tmp = i64tos(getBlockAsInteger(blockpos));
-	redisReply *reply;
-	reply = (redisReply*) redisCommand(ctx, "HGET %s %s", hash.c_str(), tmp.c_str());
+	std::string tmp = i64tos(getBlockAsInteger(pos));
+	redisReply *reply = static_cast<redisReply *>(redisCommand(ctx,
+			"HGET %s %s", hash.c_str(), tmp.c_str()));
 
-	if(!reply)
-		throw FileNotGoodException(std::string("redis command 'HGET %s %s' failed: ") + ctx->errstr);
-	if(reply->type != REDIS_REPLY_STRING)
+	if (!reply) {
+		throw FileNotGoodException(std::string(
+			"Redis command 'HGET %s %s' failed: ") + ctx->errstr);
+	} else if (reply->type != REDIS_REPLY_STRING) {
 		return "";
+	}
 
 	std::string str(reply->str, reply->len);
 	freeReplyObject(reply); // std::string copies the memory so this won't cause any problems
 	return str;
 }
 
-bool Database_Redis::deleteBlock(v3s16 blockpos)
+bool Database_Redis::deleteBlock(const v3s16 &pos)
 {
-	std::string tmp = i64tos(getBlockAsInteger(blockpos));
+	std::string tmp = i64tos(getBlockAsInteger(pos));
 
-	redisReply *reply = (redisReply *)redisCommand(ctx, "HDEL %s %s",
-		hash.c_str(), tmp.c_str());
+	redisReply *reply = static_cast<redisReply *>(redisCommand(ctx,
+		"HDEL %s %s", hash.c_str(), tmp.c_str()));
 	if (!reply) {
-		errorstream << "WARNING: deleteBlock: redis command 'HDEL' failed on "
-			"block " << PP(blockpos) << ": " << ctx->errstr << std::endl;
-		freeReplyObject(reply);
-		return false;
-	}
-
-	if (reply->type == REDIS_REPLY_ERROR) {
-		errorstream << "WARNING: deleteBlock: deleting block " << PP(blockpos)
-			<< "failed" << std::endl;
+		throw FileNotGoodException(std::string(
+			"Redis command 'HDEL %s %s' failed: ") + ctx->errstr);
+	} else if (reply->type == REDIS_REPLY_ERROR) {
+		errorstream << "WARNING: deleteBlock: deleting block " << PP(pos)
+			<< " failed" << std::endl;
 		freeReplyObject(reply);
 		return false;
 	}
@@ -149,21 +141,19 @@ bool Database_Redis::deleteBlock(v3s16 blockpos)
 
 void Database_Redis::listAllLoadableBlocks(std::vector<v3s16> &dst)
 {
-	redisReply *reply;
-	reply = (redisReply*) redisCommand(ctx, "HKEYS %s", hash.c_str());
-	if(!reply)
-		throw FileNotGoodException(std::string("redis command 'HKEYS %s' failed: ") + ctx->errstr);
-	if(reply->type != REDIS_REPLY_ARRAY)
+	redisReply *reply = static_cast<redisReply *>(redisCommand(ctx, "HKEYS %s", hash.c_str()));
+	if (!reply) {
+		throw FileNotGoodException(std::string(
+			"Redis command 'HKEYS %s' failed: ") + ctx->errstr);
+	} else if (reply->type != REDIS_REPLY_ARRAY) {
 		throw FileNotGoodException("Failed to get keys from database");
-	for(size_t i = 0; i < reply->elements; i++) {
+	}
+	for (size_t i = 0; i < reply->elements; i++) {
 		assert(reply->element[i]->type == REDIS_REPLY_STRING);
 		dst.push_back(getIntegerAsBlock(stoi64(reply->element[i]->str)));
 	}
 	freeReplyObject(reply);
 }
 
-Database_Redis::~Database_Redis()
-{
-	redisFree(ctx);
-}
-#endif
+#endif // USE_REDIS
+
diff --git a/src/database-redis.h b/src/database-redis.h
index 3c4e2b6d81507add04bacd6c769317961817d37e..45e702c83463a29c9e0a0e3e84247137ff84f2ae 100644
--- a/src/database-redis.h
+++ b/src/database-redis.h
@@ -28,24 +28,28 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include <hiredis.h>
 #include <string>
 
-class ServerMap;
+class Settings;
 
 class Database_Redis : public Database
 {
 public:
-	Database_Redis(ServerMap *map, std::string savedir);
+	Database_Redis(Settings &conf);
+	~Database_Redis();
+
 	virtual void beginSave();
 	virtual void endSave();
-	virtual bool saveBlock(v3s16 blockpos, std::string &data);
-	virtual std::string loadBlock(v3s16 blockpos);
-	virtual bool deleteBlock(v3s16 blockpos);
+
+	virtual bool saveBlock(const v3s16 &pos, const std::string &data);
+	virtual std::string loadBlock(const v3s16 &pos);
+	virtual bool deleteBlock(const v3s16 &pos);
 	virtual void listAllLoadableBlocks(std::vector<v3s16> &dst);
-	virtual int Initialized(void);
-	~Database_Redis();
+
 private:
-	ServerMap *srvmap;
 	redisContext *ctx;
 	std::string hash;
 };
+
+#endif // USE_REDIS
+
 #endif
-#endif
+
diff --git a/src/database-sqlite3.cpp b/src/database-sqlite3.cpp
index 2edae8be2e08216592e160b1c553631bc18bc830..3480894c941790f0ab48723c7495eab200fffd6c 100644
--- a/src/database-sqlite3.cpp
+++ b/src/database-sqlite3.cpp
@@ -18,259 +18,205 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 */
 
 /*
-	SQLite format specification:
-	- Initially only replaces sectors/ and sectors2/
-
-	If map.sqlite does not exist in the save dir
-	or the block was not found in the database
-	the map will try to load from sectors folder.
-	In either case, map.sqlite will be created
-	and all future saves will save there.
-
-	Structure of map.sqlite:
-	Tables:
-		blocks
-			(PK) INT pos
-			BLOB data
+SQLite format specification:
+	blocks:
+		(PK) INT id
+		BLOB data
 */
 
 
 #include "database-sqlite3.h"
 
-#include "map.h"
-#include "mapsector.h"
-#include "mapblock.h"
-#include "serialization.h"
-#include "main.h"
-#include "settings.h"
 #include "log.h"
 #include "filesys.h"
+#include "exceptions.h"
+#include "main.h"
+#include "settings.h"
+#include "util/string.h"
+
+#include <cassert>
+
+
+#define SQLRES(s, r) \
+	if ((s) != (r)) { \
+		throw FileNotGoodException(std::string(\
+					"SQLite3 database error (" \
+					__FILE__ ":" TOSTRING(__LINE__) \
+					"): ") +\
+				sqlite3_errmsg(m_database)); \
+	}
+#define SQLOK(s) SQLRES(s, SQLITE_OK)
+
+#define PREPARE_STATEMENT(name, query) \
+	SQLOK(sqlite3_prepare_v2(m_database, query, -1, &m_stmt_##name, NULL))
+
+#define FINALIZE_STATEMENT(statement) \
+	if (sqlite3_finalize(statement) != SQLITE_OK) { \
+		throw FileNotGoodException(std::string( \
+			"SQLite3: Failed to finalize " #statement ": ") + \
+			 sqlite3_errmsg(m_database)); \
+	}
 
-Database_SQLite3::Database_SQLite3(ServerMap *map, std::string savedir)
-{
-	m_database = NULL;
-	m_database_read = NULL;
-	m_database_write = NULL;
-	m_database_list = NULL;
-	m_database_delete = NULL;
-	m_savedir = savedir;
-	srvmap = map;
-}
 
-int Database_SQLite3::Initialized(void)
+Database_SQLite3::Database_SQLite3(const std::string &savedir) :
+	m_initialized(false),
+	m_savedir(savedir),
+	m_database(NULL),
+	m_stmt_read(NULL),
+	m_stmt_write(NULL),
+	m_stmt_list(NULL),
+	m_stmt_delete(NULL)
 {
-	return m_database ? 1 : 0;
 }
 
 void Database_SQLite3::beginSave() {
 	verifyDatabase();
-	if(sqlite3_exec(m_database, "BEGIN;", NULL, NULL, NULL) != SQLITE_OK)
-		errorstream<<"WARNING: beginSave() failed, saving might be slow.";
+	SQLRES(sqlite3_step(m_stmt_begin), SQLITE_DONE);
+	sqlite3_reset(m_stmt_begin);
 }
 
 void Database_SQLite3::endSave() {
 	verifyDatabase();
-	if(sqlite3_exec(m_database, "COMMIT;", NULL, NULL, NULL) != SQLITE_OK)
-		errorstream<<"WARNING: endSave() failed, map might not have saved.";
+	SQLRES(sqlite3_step(m_stmt_end), SQLITE_DONE);
+	sqlite3_reset(m_stmt_end);
 }
 
-void Database_SQLite3::createDirs(std::string path)
+void Database_SQLite3::openDatabase()
 {
-	if(fs::CreateAllDirs(path) == false)
-	{
-		infostream<<DTIME<<"Database_SQLite3: Failed to create directory "
-				<<"\""<<path<<"\""<<std::endl;
-		throw BaseException("Database_SQLite3 failed to create directory");
-	}
-}
+	if (m_database) return;
 
-void Database_SQLite3::verifyDatabase() {
-	if(m_database)
-		return;
-
-	std::string dbp = m_savedir + DIR_DELIM "map.sqlite";
-	bool needs_create = false;
-	int d;
+	std::string dbp = m_savedir + DIR_DELIM + "map.sqlite";
 
 	// Open the database connection
 
-	createDirs(m_savedir); // ?
+	if (!fs::CreateAllDirs(m_savedir)) {
+		infostream << "Database_SQLite3: Failed to create directory \""
+			<< m_savedir << "\"" << std::endl;
+		throw FileNotGoodException("Failed to create database "
+				"save directory");
+	}
 
-	if(!fs::PathExists(dbp))
-		needs_create = true;
+	bool needs_create = !fs::PathExists(dbp);
 
-	d = sqlite3_open_v2(dbp.c_str(), &m_database, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
-	if(d != SQLITE_OK) {
-		errorstream<<"SQLite3 database failed to open: "<<sqlite3_errmsg(m_database)<<std::endl;
+	if (sqlite3_open_v2(dbp.c_str(), &m_database,
+			SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
+			NULL) != SQLITE_OK) {
+		errorstream << "SQLite3 database failed to open: "
+			<< sqlite3_errmsg(m_database) << std::endl;
 		throw FileNotGoodException("Cannot open database file");
 	}
 
-	if(needs_create)
+	if (needs_create) {
 		createDatabase();
+	}
 
-	std::string querystr = std::string("PRAGMA synchronous = ")
+	std::string query_str = std::string("PRAGMA synchronous = ")
 			 + itos(g_settings->getU16("sqlite_synchronous"));
-	d = sqlite3_exec(m_database, querystr.c_str(), NULL, NULL, NULL);
-	if(d != SQLITE_OK) {
-		errorstream<<"Database pragma set failed: "
-				<<sqlite3_errmsg(m_database)<<std::endl;
-		throw FileNotGoodException("Cannot set pragma");
-	}
+	SQLOK(sqlite3_exec(m_database, query_str.c_str(), NULL, NULL, NULL));
+}
 
-	d = sqlite3_prepare(m_database, "SELECT `data` FROM `blocks` WHERE `pos`=? LIMIT 1", -1, &m_database_read, NULL);
-	if(d != SQLITE_OK) {
-		errorstream<<"SQLite3 read statment failed to prepare: "<<sqlite3_errmsg(m_database)<<std::endl;
-		throw FileNotGoodException("Cannot prepare read statement");
-	}
+void Database_SQLite3::verifyDatabase()
+{
+	if (m_initialized) return;
+
+	openDatabase();
+
+	PREPARE_STATEMENT(begin, "BEGIN");
+	PREPARE_STATEMENT(end, "COMMIT");
+	PREPARE_STATEMENT(read, "SELECT `data` FROM `blocks` WHERE `pos` = ? LIMIT 1");
 #ifdef __ANDROID__
-	d = sqlite3_prepare(m_database, "INSERT INTO `blocks` VALUES(?, ?);", -1, &m_database_write, NULL);
+	PREPARE_STATEMENT(write,  "INSERT INTO `blocks` (`pos`, `data`) VALUES (?, ?)");
 #else
-	d = sqlite3_prepare(m_database, "REPLACE INTO `blocks` VALUES(?, ?);", -1, &m_database_write, NULL);
+	PREPARE_STATEMENT(write, "REPLACE INTO `blocks` (`pos`, `data`) VALUES (?, ?)");
 #endif
-	if(d != SQLITE_OK) {
-		errorstream<<"SQLite3 write statment failed to prepare: "<<sqlite3_errmsg(m_database)<<std::endl;
-		throw FileNotGoodException("Cannot prepare write statement");
-	}
+	PREPARE_STATEMENT(delete, "DELETE FROM `blocks` WHERE `pos` = ?");
+	PREPARE_STATEMENT(list, "SELECT `pos` FROM `blocks`");
 
-	d = sqlite3_prepare(m_database, "DELETE FROM `blocks` WHERE `pos`=?;", -1, &m_database_delete, NULL);
-	if(d != SQLITE_OK) {
-		infostream<<"WARNING: SQLite3 database delete statment failed to prepare: "<<sqlite3_errmsg(m_database)<<std::endl;
-		throw FileNotGoodException("Cannot prepare delete statement");
-	}
+	m_initialized = true;
 
-	d = sqlite3_prepare(m_database, "SELECT `pos` FROM `blocks`", -1, &m_database_list, NULL);
-	if(d != SQLITE_OK) {
-		infostream<<"SQLite3 list statment failed to prepare: "<<sqlite3_errmsg(m_database)<<std::endl;
-		throw FileNotGoodException("Cannot prepare read statement");
-	}
+	verbosestream << "ServerMap: SQLite3 database opened." << std::endl;
+}
 
-	infostream<<"ServerMap: SQLite3 database opened"<<std::endl;
+inline void Database_SQLite3::bindPos(sqlite3_stmt *stmt, const v3s16 &pos, int index)
+{
+	SQLOK(sqlite3_bind_int64(stmt, index, getBlockAsInteger(pos)));
 }
 
-bool Database_SQLite3::deleteBlock(v3s16 blockpos)
+bool Database_SQLite3::deleteBlock(const v3s16 &pos)
 {
 	verifyDatabase();
 
-	if (sqlite3_bind_int64(m_database_delete, 1,
-			getBlockAsInteger(blockpos)) != SQLITE_OK) {
-		errorstream << "WARNING: Could not bind block position for delete: "
-			<< sqlite3_errmsg(m_database) << std::endl;
-	}
+	bindPos(m_stmt_delete, pos);
+
+	bool good = sqlite3_step(m_stmt_delete) == SQLITE_DONE;
+	sqlite3_reset(m_stmt_delete);
 
-	if (sqlite3_step(m_database_delete) != SQLITE_DONE) {
+	if (!good) {
 		errorstream << "WARNING: deleteBlock: Block failed to delete "
-			<< PP(blockpos) << ": " << sqlite3_errmsg(m_database) << std::endl;
-		sqlite3_reset(m_database_delete);
-		return false;
+			<< PP(pos) << ": " << sqlite3_errmsg(m_database) << std::endl;
 	}
-
-	sqlite3_reset(m_database_delete);
-	return true;
+	return good;
 }
 
-bool Database_SQLite3::saveBlock(v3s16 blockpos, std::string &data)
+bool Database_SQLite3::saveBlock(const v3s16 &pos, const std::string &data)
 {
 	verifyDatabase();
 
-	s64 bkey = getBlockAsInteger(blockpos);
-
 #ifdef __ANDROID__
 	/**
-	 * Note: For some unknown reason sqlite3 fails to REPLACE blocks on android,
-	 * deleting them and inserting first works.
+	 * Note: For some unknown reason SQLite3 fails to REPLACE blocks on Android,
+	 * deleting them and then inserting works.
 	 */
-	if (sqlite3_bind_int64(m_database_read, 1, bkey) != SQLITE_OK) {
-		infostream << "WARNING: Could not bind block position for load: "
-			<< sqlite3_errmsg(m_database)<<std::endl;
-	}
+	bindPos(m_stmt_read, pos);
 
-	int step_result = sqlite3_step(m_database_read);
-	sqlite3_reset(m_database_read);
-
-	if (step_result == SQLITE_ROW) {
-		if (sqlite3_bind_int64(m_database_delete, 1, bkey) != SQLITE_OK) {
-			infostream << "WARNING: Could not bind block position for delete: "
-				<< sqlite3_errmsg(m_database)<<std::endl;
-		}
-
-		if (sqlite3_step(m_database_delete) != SQLITE_DONE) {
-			errorstream << "WARNING: saveBlock: Block failed to delete "
-				<< PP(blockpos) << ": " << sqlite3_errmsg(m_database) << std::endl;
-			return false;
-		}
-		sqlite3_reset(m_database_delete);
+	if (sqlite3_step(m_stmt_read) == SQLITE_ROW) {
+		deleteBlock(pos);
 	}
+	sqlite3_reset(m_stmt_read);
 #endif
 
-	if (sqlite3_bind_int64(m_database_write, 1, bkey) != SQLITE_OK) {
-		errorstream << "WARNING: saveBlock: Block position failed to bind: "
-			<< PP(blockpos) << ": " << sqlite3_errmsg(m_database) << std::endl;
-		sqlite3_reset(m_database_write);
-		return false;
-	}
-
-	if (sqlite3_bind_blob(m_database_write, 2, (void *)data.c_str(),
-			data.size(), NULL) != SQLITE_OK) {
-		errorstream << "WARNING: saveBlock: Block data failed to bind: "
-			<< PP(blockpos) << ": " << sqlite3_errmsg(m_database) << std::endl;
-		sqlite3_reset(m_database_write);
-		return false;
-	}
-
-	if (sqlite3_step(m_database_write) != SQLITE_DONE) {
-		errorstream << "WARNING: saveBlock: Block failed to save "
-			<< PP(blockpos) << ": " << sqlite3_errmsg(m_database) << std::endl;
-		sqlite3_reset(m_database_write);
-		return false;
-	}
+	bindPos(m_stmt_write, pos);
+	SQLOK(sqlite3_bind_blob(m_stmt_write, 2, data.data(), data.size(), NULL));
 
-	sqlite3_reset(m_database_write);
+	SQLRES(sqlite3_step(m_stmt_write), SQLITE_DONE)
+	sqlite3_reset(m_stmt_write);
 
 	return true;
 }
 
-std::string Database_SQLite3::loadBlock(v3s16 blockpos)
+std::string Database_SQLite3::loadBlock(const v3s16 &pos)
 {
 	verifyDatabase();
 
-	if (sqlite3_bind_int64(m_database_read, 1, getBlockAsInteger(blockpos)) != SQLITE_OK) {
-		errorstream << "Could not bind block position for load: "
-			<< sqlite3_errmsg(m_database)<<std::endl;
-	}
+	bindPos(m_stmt_read, pos);
 
-	if (sqlite3_step(m_database_read) == SQLITE_ROW) {
-		const char *data = (const char *) sqlite3_column_blob(m_database_read, 0);
-		size_t len = sqlite3_column_bytes(m_database_read, 0);
-
-		std::string s = "";
-		if(data)
-			s = std::string(data, len);
+	if (sqlite3_step(m_stmt_read) != SQLITE_ROW) {
+		sqlite3_reset(m_stmt_read);
+		return "";
+	}
+	const char *data = (const char *) sqlite3_column_blob(m_stmt_read, 0);
+	size_t len = sqlite3_column_bytes(m_stmt_read, 0);
 
-		sqlite3_step(m_database_read);
-		// We should never get more than 1 row, so ok to reset
-		sqlite3_reset(m_database_read);
+	std::string s;
+	if (data)
+		s = std::string(data, len);
 
-		return s;
-	}
+	sqlite3_step(m_stmt_read);
+	// We should never get more than 1 row, so ok to reset
+	sqlite3_reset(m_stmt_read);
 
-	sqlite3_reset(m_database_read);
-	return "";
+	return s;
 }
 
 void Database_SQLite3::createDatabase()
 {
-	int e;
 	assert(m_database);
-	e = sqlite3_exec(m_database,
-		"CREATE TABLE IF NOT EXISTS `blocks` ("
-			"`pos` INT NOT NULL PRIMARY KEY,"
-			"`data` BLOB"
-		");"
-	, NULL, NULL, NULL);
-	if(e != SQLITE_OK)
-		throw FileNotGoodException("Could not create sqlite3 database structure");
-	else
-		infostream<<"ServerMap: SQLite3 database structure was created";
+	SQLOK(sqlite3_exec(m_database,
+		"CREATE TABLE IF NOT EXISTS `blocks` (\n"
+		"	`pos` INT PRIMARY KEY,\n"
+		"	`data` BLOB\n"
+		");\n",
+		NULL, NULL, NULL));
 
 }
 
@@ -278,36 +224,25 @@ void Database_SQLite3::listAllLoadableBlocks(std::vector<v3s16> &dst)
 {
 	verifyDatabase();
 
-	while(sqlite3_step(m_database_list) == SQLITE_ROW) {
-		sqlite3_int64 block_i = sqlite3_column_int64(m_database_list, 0);
-		v3s16 p = getIntegerAsBlock(block_i);
-		//dstream<<"block_i="<<block_i<<" p="<<PP(p)<<std::endl;
-		dst.push_back(p);
+	while (sqlite3_step(m_stmt_list) == SQLITE_ROW) {
+		dst.push_back(getIntegerAsBlock(sqlite3_column_int64(m_stmt_list, 0)));
 	}
+	sqlite3_reset(m_stmt_list);
 }
 
-
-#define FINALIZE_STATEMENT(statement)                                          \
-	if ( statement )                                                           \
-		rc = sqlite3_finalize(statement);                                      \
-	if ( rc != SQLITE_OK )                                                     \
-		errorstream << "Database_SQLite3::~Database_SQLite3():"                \
-			<< "Failed to finalize: " << #statement << ": rc=" << rc << std::endl;
-
 Database_SQLite3::~Database_SQLite3()
 {
-	int rc = SQLITE_OK;
-
-	FINALIZE_STATEMENT(m_database_read)
-	FINALIZE_STATEMENT(m_database_write)
-	FINALIZE_STATEMENT(m_database_list)
-	FINALIZE_STATEMENT(m_database_delete)
-
-	if(m_database)
-		rc = sqlite3_close(m_database);
-
-	if (rc != SQLITE_OK) {
+	FINALIZE_STATEMENT(m_stmt_read)
+	FINALIZE_STATEMENT(m_stmt_write)
+	FINALIZE_STATEMENT(m_stmt_list)
+	FINALIZE_STATEMENT(m_stmt_begin)
+	FINALIZE_STATEMENT(m_stmt_end)
+	FINALIZE_STATEMENT(m_stmt_delete)
+
+	if (sqlite3_close(m_database) != SQLITE_OK) {
 		errorstream << "Database_SQLite3::~Database_SQLite3(): "
-				<< "Failed to close database: rc=" << rc << std::endl;
+				<< "Failed to close database: "
+				<< sqlite3_errmsg(m_database) << std::endl;
 	}
 }
+
diff --git a/src/database-sqlite3.h b/src/database-sqlite3.h
index 270e4e3be549fa47a2c81ac940feb9aef98a91e4..a775742be83ba1ef241b3575147a4858e61b7c9d 100644
--- a/src/database-sqlite3.h
+++ b/src/database-sqlite3.h
@@ -27,35 +27,43 @@ extern "C" {
 	#include "sqlite3.h"
 }
 
-class ServerMap;
-
 class Database_SQLite3 : public Database
 {
 public:
-	Database_SQLite3(ServerMap *map, std::string savedir);
+	Database_SQLite3(const std::string &savedir);
+
 	virtual void beginSave();
 	virtual void endSave();
 
-	virtual bool saveBlock(v3s16 blockpos, std::string &data);
-	virtual std::string loadBlock(v3s16 blockpos);
-	virtual bool deleteBlock(v3s16 blockpos);
+	virtual bool saveBlock(const v3s16 &pos, const std::string &data);
+	virtual std::string loadBlock(const v3s16 &pos);
+	virtual bool deleteBlock(const v3s16 &pos);
 	virtual void listAllLoadableBlocks(std::vector<v3s16> &dst);
-	virtual int Initialized(void);
+	virtual bool initialized() const { return m_initialized; }
 	~Database_SQLite3();
-private:
-	ServerMap *srvmap;
-	std::string m_savedir;
-	sqlite3 *m_database;
-	sqlite3_stmt *m_database_read;
-	sqlite3_stmt *m_database_write;
-	sqlite3_stmt *m_database_delete;
-	sqlite3_stmt *m_database_list;
 
+private:
+	// Open the database
+	void openDatabase();
 	// Create the database structure
 	void createDatabase();
-	// Verify we can read/write to the database
+	// Open and initialize the database if needed
 	void verifyDatabase();
-	void createDirs(std::string path);
+
+	void bindPos(sqlite3_stmt *stmt, const v3s16 &pos, int index=1);
+
+	bool m_initialized;
+
+	std::string m_savedir;
+
+	sqlite3 *m_database;
+	sqlite3_stmt *m_stmt_read;
+	sqlite3_stmt *m_stmt_write;
+	sqlite3_stmt *m_stmt_list;
+	sqlite3_stmt *m_stmt_delete;
+	sqlite3_stmt *m_stmt_begin;
+	sqlite3_stmt *m_stmt_end;
 };
 
 #endif
+
diff --git a/src/database.cpp b/src/database.cpp
index 26f6992fcb47e7e84b5fad70707857fcaa1cd857..262d475ec5554b25c5c4f2a6b8331dfedf3e2ef8 100644
--- a/src/database.cpp
+++ b/src/database.cpp
@@ -48,7 +48,7 @@ static inline s64 pythonmodulo(s64 i, s16 mod)
 }
 
 
-s64 Database::getBlockAsInteger(const v3s16 pos) const
+s64 Database::getBlockAsInteger(const v3s16 &pos)
 {
 	return (u64) pos.Z * 0x1000000 +
 		(u64) pos.Y * 0x1000 +
@@ -56,7 +56,7 @@ s64 Database::getBlockAsInteger(const v3s16 pos) const
 }
 
 
-v3s16 Database::getIntegerAsBlock(s64 i) const
+v3s16 Database::getIntegerAsBlock(s64 i)
 {
 	v3s16 pos;
 	pos.X = unsigned_to_signed(pythonmodulo(i, 4096), 2048);
diff --git a/src/database.h b/src/database.h
index f4a2a4e8c85774bec999dfc75feec1b422393daf..cee7b6fd96d5589869ee2a5a9aa322193521923b 100644
--- a/src/database.h
+++ b/src/database.h
@@ -32,16 +32,22 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 class Database
 {
 public:
-	virtual void beginSave() = 0;
-	virtual void endSave() = 0;
-
-	virtual bool saveBlock(v3s16 blockpos, std::string &data) = 0;
-	virtual std::string loadBlock(v3s16 blockpos) = 0;
-	virtual bool deleteBlock(v3s16 blockpos) = 0;
-	s64 getBlockAsInteger(const v3s16 pos) const;
-	v3s16 getIntegerAsBlock(s64 i) const;
+	virtual ~Database() {}
+
+	virtual void beginSave() {}
+	virtual void endSave() {}
+
+	virtual bool saveBlock(const v3s16 &pos, const std::string &data) = 0;
+	virtual std::string loadBlock(const v3s16 &pos) = 0;
+	virtual bool deleteBlock(const v3s16 &pos) = 0;
+
+	static s64 getBlockAsInteger(const v3s16 &pos);
+	static v3s16 getIntegerAsBlock(s64 i);
+
 	virtual void listAllLoadableBlocks(std::vector<v3s16> &dst) = 0;
-	virtual int Initialized(void)=0;
-	virtual ~Database() {};
+
+	virtual bool initialized() const { return true; }
 };
+
 #endif
+
diff --git a/src/main.cpp b/src/main.cpp
index 922effb1f38af57b2a87dc3e80553c275723d6b8..4e5bf51fd2b690676992e51a8eaf2393eaac3e98 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -914,52 +914,46 @@ static bool run_dedicated_server(const GameParams &game_params, const Settings &
 static bool migrate_database(const GameParams &game_params, const Settings &cmd_args,
 		Server *server)
 {
+	std::string migrate_to = cmd_args.get("migrate");
 	Settings world_mt;
-	bool success = world_mt.readConfigFile((game_params.world_path
-			+ DIR_DELIM + "world.mt").c_str());
+	std::string world_mt_path = game_params.world_path + DIR_DELIM + "world.mt";
+	bool success = world_mt.readConfigFile(world_mt_path.c_str());
 	if (!success) {
 		errorstream << "Cannot read world.mt" << std::endl;
-		return false;
+		return 1;
 	}
-
 	if (!world_mt.exists("backend")) {
-		errorstream << "Please specify your current backend in world.mt file:"
-		            << std::endl << "	backend = {sqlite3|leveldb|redis|dummy}"
-		            << std::endl;
-		return false;
+		errorstream << "Please specify your current backend in world.mt:"
+			<< std::endl;
+		errorstream << "	backend = {sqlite3|leveldb|redis|dummy}"
+			<< std::endl;
+		return 1;
 	}
-
 	std::string backend = world_mt.get("backend");
 	Database *new_db;
-	std::string migrate_to = cmd_args.get("migrate");
-
 	if (backend == migrate_to) {
-		errorstream << "Cannot migrate: new backend is same as the old one"
-		            << std::endl;
-		return false;
+		errorstream << "Cannot migrate: new backend is same"
+			<<" as the old one" << std::endl;
+		return 1;
 	}
-
 	if (migrate_to == "sqlite3")
-		new_db = new Database_SQLite3(&(ServerMap&)server->getMap(),
-				game_params.world_path);
-#if USE_LEVELDB
+		new_db = new Database_SQLite3(game_params.world_path);
+	#if USE_LEVELDB
 	else if (migrate_to == "leveldb")
-		new_db = new Database_LevelDB(&(ServerMap&)server->getMap(),
-				game_params.world_path);
-#endif
-#if USE_REDIS
+		new_db = new Database_LevelDB(game_params.world_path);
+	#endif
+	#if USE_REDIS
 	else if (migrate_to == "redis")
-		new_db = new Database_Redis(&(ServerMap&)server->getMap(),
-				game_params.world_path);
-#endif
+		new_db = new Database_Redis(world_mt);
+	#endif
 	else {
-		errorstream << "Migration to " << migrate_to << " is not supported"
-		            << std::endl;
-		return false;
+		errorstream << "Migration to " << migrate_to
+			<< " is not supported" << std::endl;
+		return 1;
 	}
 
 	std::vector<v3s16> blocks;
-	ServerMap &old_map = ((ServerMap&)server->getMap());
+	ServerMap &old_map = (ServerMap &) server->getMap();
 	old_map.listAllLoadableBlocks(blocks);
 	int count = 0;
 	new_db->beginSave();
@@ -975,16 +969,15 @@ static bool migrate_database(const GameParams &game_params, const Settings &cmd_
 		}
 		++count;
 		if (count % 500 == 0)
-		   actionstream << "Migrated " << count << " blocks "
-			   << (100.0 * count / blocks.size()) << "% completed" << std::endl;
+			actionstream << "Migrated " << count << " blocks "
+				<< (100.0 * count / blocks.size()) << "% completed" << std::endl;
 	}
 	new_db->endSave();
 	delete new_db;
 
 	actionstream << "Successfully migrated " << count << " blocks" << std::endl;
 	world_mt.set("backend", migrate_to);
-	if (!world_mt.updateConfigFile(
-				(game_params.world_path+ DIR_DELIM + "world.mt").c_str()))
+	if (!world_mt.updateConfigFile(world_mt_path.c_str()))
 		errorstream << "Failed to update world.mt!" << std::endl;
 	else
 		actionstream << "world.mt updated" << std::endl;
diff --git a/src/map.cpp b/src/map.cpp
index 2c70280095b47f4c5cdfd31097d05a8eb85ed199..e58ae2cfe3a0a9c59bcf47e6be03d7778cd4a832 100644
--- a/src/map.cpp
+++ b/src/map.cpp
@@ -53,22 +53,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 
 #define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
 
-/*
-	SQLite format specification:
-	- Initially only replaces sectors/ and sectors2/
-
-	If map.sqlite does not exist in the save dir
-	or the block was not found in the database
-	the map will try to load from sectors folder.
-	In either case, map.sqlite will be created
-	and all future saves will save there.
-
-	Structure of map.sqlite:
-	Tables:
-		blocks
-			(PK) INT pos
-			BLOB data
-*/
 
 /*
 	Map
@@ -2031,25 +2015,26 @@ ServerMap::ServerMap(std::string savedir, IGameDef *gamedef, EmergeManager *emer
 	bool succeeded = conf.readConfigFile(conf_path.c_str());
 	if (!succeeded || !conf.exists("backend")) {
 		// fall back to sqlite3
-		dbase = new Database_SQLite3(this, savedir);
 		conf.set("backend", "sqlite3");
-	} else {
-		std::string backend = conf.get("backend");
-		if (backend == "dummy")
-			dbase = new Database_Dummy(this);
-		else if (backend == "sqlite3")
-			dbase = new Database_SQLite3(this, savedir);
-		#if USE_LEVELDB
-		else if (backend == "leveldb")
-			dbase = new Database_LevelDB(this, savedir);
-		#endif
-		#if USE_REDIS
-		else if (backend == "redis")
-			dbase = new Database_Redis(this, savedir);
-		#endif
-		else
-			throw BaseException("Unknown map backend");
 	}
+	std::string backend = conf.get("backend");
+	if (backend == "dummy")
+		dbase = new Database_Dummy();
+	else if (backend == "sqlite3")
+		dbase = new Database_SQLite3(savedir);
+	#if USE_LEVELDB
+	else if (backend == "leveldb")
+		dbase = new Database_LevelDB(savedir);
+	#endif
+	#if USE_REDIS
+	else if (backend == "redis")
+		dbase = new Database_Redis(conf);
+	#endif
+	else
+		throw BaseException("Unknown map backend");
+
+	if (!conf.updateConfigFile(conf_path.c_str()))
+		errorstream << "ServerMap::ServerMap(): Failed to update world.mt!" << std::endl;
 
 	m_savedir = savedir;
 	m_map_saving_enabled = false;
@@ -2828,7 +2813,8 @@ s16 ServerMap::findGroundLevel(v2s16 p2d)
 }
 
 bool ServerMap::loadFromFolders() {
-	if(!dbase->Initialized() && !fs::PathExists(m_savedir + DIR_DELIM + "map.sqlite")) // ?
+	if(!dbase->initialized() &&
+			!fs::PathExists(m_savedir + DIR_DELIM + "map.sqlite"))
 		return true;
 	return false;
 }
@@ -2850,14 +2836,14 @@ std::string ServerMap::getSectorDir(v2s16 pos, int layout)
 	{
 		case 1:
 			snprintf(cc, 9, "%.4x%.4x",
-				(unsigned int)pos.X&0xffff,
-				(unsigned int)pos.Y&0xffff);
+				(unsigned int) pos.X & 0xffff,
+				(unsigned int) pos.Y & 0xffff);
 
 			return m_savedir + DIR_DELIM + "sectors" + DIR_DELIM + cc;
 		case 2:
-			snprintf(cc, 9, "%.3x" DIR_DELIM "%.3x",
-				(unsigned int)pos.X&0xfff,
-				(unsigned int)pos.Y&0xfff);
+			snprintf(cc, 9, (std::string("%.3x") + DIR_DELIM + "%.3x").c_str(),
+				(unsigned int) pos.X & 0xfff,
+				(unsigned int) pos.Y & 0xfff);
 
 			return m_savedir + DIR_DELIM + "sectors2" + DIR_DELIM + cc;
 		default:
@@ -2881,10 +2867,10 @@ v2s16 ServerMap::getSectorPos(std::string dirname)
 	{
 		// New layout
 		fs::RemoveLastPathComponent(dirname, &component, 2);
-		r = sscanf(component.c_str(), "%3x" DIR_DELIM "%3x", &x, &y);
+		r = sscanf(component.c_str(), (std::string("%3x") + DIR_DELIM + "%3x").c_str(), &x, &y);
 		// Sign-extend the 12 bit values up to 16 bits...
-		if(x&0x800) x|=0xF000;
-		if(y&0x800) y|=0xF000;
+		if(x & 0x800) x |= 0xF000;
+		if(y & 0x800) y |= 0xF000;
 	}
 	else
 	{
@@ -3299,7 +3285,7 @@ bool ServerMap::saveBlock(MapBlock *block, Database *db)
 
 	std::string data = o.str();
 	bool ret = db->saveBlock(p3d, data);
-	if(ret) {
+	if (ret) {
 		// We just wrote it to the disk so clear modified flag
 		block->resetModified();
 	}
@@ -3311,7 +3297,7 @@ void ServerMap::loadBlock(std::string sectordir, std::string blockfile,
 {
 	DSTACK(__FUNCTION_NAME);
 
-	std::string fullpath = sectordir+DIR_DELIM+blockfile;
+	std::string fullpath = sectordir + DIR_DELIM + blockfile;
 	try {
 
 		std::ifstream is(fullpath.c_str(), std::ios_base::binary);
@@ -3513,7 +3499,7 @@ MapBlock* ServerMap::loadBlock(v3s16 blockpos)
 	*/
 
 	std::string blockfilename = getBlockFilename(blockpos);
-	if(fs::PathExists(sectordir+DIR_DELIM+blockfilename) == false)
+	if(fs::PathExists(sectordir + DIR_DELIM + blockfilename) == false)
 		return NULL;
 
 	/*
diff --git a/src/map.h b/src/map.h
index ab5f45ab96443920652dfca62f62e18174d2674b..073f9314dba3abeeb96c9c6bf20fb3b5b9c382c4 100644
--- a/src/map.h
+++ b/src/map.h
@@ -481,8 +481,8 @@ class ServerMap : public Map
 	// Returns true if sector now resides in memory
 	//bool deFlushSector(v2s16 p2d);
 
-	bool saveBlock(MapBlock *block, Database *db);
 	bool saveBlock(MapBlock *block);
+	static bool saveBlock(MapBlock *block, Database *db);
 	// This will generate a sector with getSector if not found.
 	void loadBlock(std::string sectordir, std::string blockfile, MapSector *sector, bool save_after_load=false);
 	MapBlock* loadBlock(v3s16 p);
diff --git a/src/network/packethandlers/client.cpp b/src/network/packethandlers/client.cpp
index e1e57b3a656d94c011b2aa14eb9c4cc7b84c2204..82f8b61b7244fb5f476bba443b0054c64c8c0cad 100644
--- a/src/network/packethandlers/client.cpp
+++ b/src/network/packethandlers/client.cpp
@@ -168,8 +168,8 @@ void Client::handleCommand_BlockData(NetworkPacket* pkt)
 		sector->insertBlock(block);
 	}
 
-	if (localdb != NULL) {
-		((ServerMap&) localserver->getMap()).saveBlock(block, localdb);
+	if (m_localdb) {
+		ServerMap::saveBlock(block, m_localdb);
 	}
 
 	/*