+ Server server(world_path, gamespec, false, bind_addr.isIPv6());
+
+ // Database migration
+ if (cmd_args.exists("migrate")) {
+ std::string migrate_to = cmd_args.get("migrate");
+ Settings world_mt;
+ bool success = world_mt.readConfigFile((world_path + DIR_DELIM
+ + "world.mt").c_str());
+ if (!success) {
+ errorstream << "Cannot read world.mt" << std::endl;
+ 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 1;
+ }
+ std::string backend = world_mt.get("backend");
+ Database *new_db;
+ if (backend == migrate_to) {
+ 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(), world_path);
+ #if USE_LEVELDB
+ else if (migrate_to == "leveldb")
+ new_db = new Database_LevelDB(&(ServerMap&)server.getMap(), world_path);
+ #endif
+ #if USE_REDIS
+ else if (migrate_to == "redis")
+ new_db = new Database_Redis(&(ServerMap&)server.getMap(), world_path);
+ #endif
+ else {
+ errorstream << "Migration to " << migrate_to
+ << " is not supported" << std::endl;
+ return 1;
+ }
+
+ std::list<v3s16> blocks;
+ ServerMap &old_map = ((ServerMap&)server.getMap());
+ old_map.listAllLoadableBlocks(blocks);
+ int count = 0;
+ new_db->beginSave();
+ for (std::list<v3s16>::iterator i = blocks.begin(); i != blocks.end(); i++) {
+ MapBlock *block = old_map.loadBlock(*i);
+ if (!block) {
+ errorstream << "Failed to load block " << PP(*i) << ", skipping it.";
+ } else {
+ old_map.saveBlock(block, new_db);
+ MapSector *sector = old_map.getSectorNoGenerate(v2s16(i->X, i->Z));
+ sector->deleteBlock(block);
+ }
+ ++count;
+ if (count % 500 == 0)
+ 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((world_path + DIR_DELIM + "world.mt").c_str()))
+ errorstream << "Failed to update world.mt!" << std::endl;
+ else
+ actionstream << "world.mt updated" << std::endl;
+
+ return 0;
+ }
+
+ server.start(bind_addr);
+