diff --git a/minetest.conf.example b/minetest.conf.example index 345a52bcd..6bd2e00b4 100644 --- a/minetest.conf.example +++ b/minetest.conf.example @@ -164,6 +164,8 @@ #selectionbox_width = 2 # maximum percentage of current window to be used for hotbar #hud_hotbar_max_width = 1.0 +# Save the map received by the client on disk +#enable_local_map_saving = false # Enable highlighting for nodes (disables selectionboxes) #enable_node_highlighting = false # Texture filtering settings 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");