From 9d69436052c32bc218352fc991be157a4f135b9d Mon Sep 17 00:00:00 2001
From: sfan5 <sfan5@live.de>
Date: Thu, 9 Oct 2014 14:02:02 +0200
Subject: Add (optional) client-side saving of server map to disk

---
 src/client.cpp          | 39 +++++++++++++++++++++++++++++++++++++++
 src/client.h            |  6 ++++++
 src/defaultsettings.cpp |  1 +
 3 files changed, 46 insertions(+)

(limited to 'src')

diff --git a/src/client.cpp b/src/client.cpp
index 89bb053ae..c1806df99 100644
--- a/src/client.cpp
+++ b/src/client.cpp
@@ -52,6 +52,10 @@ 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"
 
 extern gui::IGUIEnvironment* guienv;
 
@@ -275,12 +279,43 @@ Client::Client(
 
 		m_env.addPlayer(player);
 	}
+
+	if (g_settings->getBool("enable_local_map_saving")) {
+		const std::string world_path = porting::path_user + DIR_DELIM + "worlds"
+				+ DIR_DELIM + "server_" + g_settings->get("address")
+				+ "_" + g_settings->get("remote_port");
+
+		SubgameSpec gamespec;
+		if (!getWorldExists(world_path)) {
+			gamespec = findSubgame(g_settings->get("default_game"));
+			if (!gamespec.isValid())
+				gamespec = findSubgame("minimal");
+		} else {
+			std::string world_gameid = getWorldGameId(world_path, false);
+			gamespec = findWorldSubgame(world_path);
+		}
+		if (!gamespec.isValid()) {
+			errorstream << "Couldn't find subgame for local map saving." << std::endl;
+			return;
+		}
+
+		localserver = new Server(world_path, gamespec, false, false);
+		localdb = new Database_SQLite3(&(ServerMap&)localserver->getMap(), world_path);
+		localdb->beginSave();
+		actionstream << "Local map saving started, map will be saved at '" << world_path << "'" << std::endl;
+	} else {
+		localdb = NULL;
+	}
 }
 
 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();
+	}
 }
 
 bool Client::isShutdown()
@@ -1156,6 +1191,10 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
 			sector->insertBlock(block);
 		}
 
+		if (localdb != NULL) {
+			((ServerMap&) localserver->getMap()).saveBlock(block, localdb);
+		}
+
 		/*
 			Add it to mesh update queue and set it to be acknowledged after update.
 		*/
diff --git a/src/client.h b/src/client.h
index 084f7be2c..e41410f14 100644
--- a/src/client.h
+++ b/src/client.h
@@ -46,6 +46,8 @@ class ClientMediaDownloader;
 struct MapDrawControl;
 class MtEventManager;
 struct PointedThing;
+class Database;
+class Server;
 
 struct QueuedMeshUpdate
 {
@@ -555,6 +557,10 @@ private:
 
 	// own state
 	LocalClientState m_state;
+
+	// Used for saving server map to disk client-side
+	Database *localdb;
+	Server *localserver;
 };
 
 #endif // !CLIENT_HEADER
diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp
index 32a920ed3..4f297c099 100644
--- a/src/defaultsettings.cpp
+++ b/src/defaultsettings.cpp
@@ -131,6 +131,7 @@ void set_default_settings(Settings *settings)
 	settings->setDefault("desynchronize_mapblock_texture_animation", "true");
 	settings->setDefault("selectionbox_width","2");
 	settings->setDefault("hud_hotbar_max_width","1.0");
+	settings->setDefault("enable_local_map_saving", "false");
 
 	settings->setDefault("mip_map", "false");
 	settings->setDefault("anisotropic_filter", "false");
-- 
cgit v1.2.3